首页 > Java知识 > JavaSE > 15-IO流 > 应用案例
2022
04-08
温馨提示:此处内容需要登录或VIP权限才能查看!请联系管理员升级您的用户权限!

IO的开发操作在整个Java设计中非常的繁琐,为了方便后续对于程序开发的理解,我们将通过一些具体的输入输出的操作代码来提升对于IO的巩固。

案例1:输入数据比大小

编写Java程序,输入3个整数,并求出三个整数的最大值和最小值。

首先既然要进行键盘数据的输入,可以通过Scanner或者BufferedReader两个类完成,如果单纯键盘数据输入的话,BufferedReader更为方便,那么就可以定义一个键盘输入类。

 public class InputUtil {
     private static final BufferedReader INPUT = new BufferedReader(new InputStreamReader(System.in));
 ​
     private InputUtil() {
     }
     
     private static String getString(String prompt) {
         System.out.println(prompt);
         try {
             String value = INPUT.readLine();
             return value;
         } catch (Exception e) {
             return null;
         }
     }
     
     public static int getInt(String prompt) {
         while (true) {
             String value = getString(prompt);
             if (value != null) {
                 if (value.matches("\\d+")) {
                     return Integer.parseInt(value);
                 } else {
                     System.out.println("【错误】输入的数据必须为整型,请重新输入!");
                 }
             }
         }
     }
 ​
 }

所有的程序设计都应该按照面向对象的设计要求进行处理,那么既然是面向对象则一定要有相关的程序处理类。那么应该首先创建有一个数据处理的功能业务接口,然后设计它的子类。

 public interface INumberService {
     public int max();
     public int min();
 }

如果中间出现问题,应该有一个异常类进行处理,所以建立异常类。

 public class ArrayLengthInvalidateException extends RuntimeException {
     public ArrayLengthInvalidateException(String msg) {
         super(msg);
     }
 }

以上内容有了之后,就应该创建实现子类。

 public class NumberServiceImpl implements INumberService {
     private static final int DEFAULT_LEN = 3;
     private int data[];
     private int maxValue;
     private int minValue;
 ​
     public NumberServiceImpl() {
         this(DEFAULT_LEN);
     }
     
     public NumberServiceImpl(int len) {
         if (len <= 0) {
             throw new ArrayLengthInvalidateException("开辟的数据长度错误!");
         } else {
             this.data = new int[len];
         }
         this.inputData();
         this.handleData();
     }
     
     public void inputData() {
         for (int i = 0; i < this.data.length; i++) {
             this.data[i] = InputUtil.getInt("请输入第" + (i + 1) + "个数据:");
         }
     }
     
     private void handleData() {
         this.maxValue = this.data[0];
         this.minValue = this.data[0];
         for (int temp : this.data) {
             if (maxValue < temp) {
                 maxValue = temp;
             }
             if (minValue > temp) {
                 minValue = temp;
             }
         }
     }
     
     @Override
     public int max() {
         return this.maxValue;
     }
     
     @Override
     public int min() {
         return this.minValue;
     }
 ​
 }

编写程序的工厂类,获取业务实例。

 public class ServiceFactory {
     private ServiceFactory() {
     }
 ​
     public static INumberService getInstance(int...args) {
         if(args.length == 1){
             return new NumberServiceImpl(args[0]);
         }
         return new NumberServiceImpl();
     }
 ​
 }

程序执行验证:

 public class TestDemo01 {
     public static void main(String[] args) {
         INumberService numberService = ServiceFactory.getInstance();
         System.out.println("【输入数据最大值】" + numberService.max());
         System.out.println("【输入数据最小值】" + numberService.min());
     }
 }
程序执行结果
请输入第1个数据:
14
请输入第2个数据:
22
请输入第3个数据:
7
【输入数据最大值】22
【输入数据最小值】7

Java不是面向过程的编程开发,既然不是面向过程,所以所有的代码就必须尤其完整的设计功能类结构存在。如果这个结构设计的不合理,那么整个程序代码就会出现维护性的问题。

有功能,写功能,有业务异常写异常,一切从接口开始,到工厂结束,而这种设计就是一个完整的设计模式,只有把握住这种面向对象的设计精髓,才能真正走入正轨的设计之路。

案例2:字符串逆序处理

从键盘传入多个字符串到程序中,并逆序输出。

如果此时要想实现内容输入,需要一个键盘输入类,而这个输入类已经有相关支持,就不需要写该类了。 那么现在的问题是如何逆序的问题。

此时应该是按照完整字符串的顺序进行逆序的处理,而不应该是将多个字符串合并在一起之后再逆序输出。

 public interface IStringService{
     public void input();
     public String value();
 }
 import java.util.Arrays;
 ​
 public class StringServiceImpl implements IStringService {
     private static final int DEFAULT_LENGTH = 5;
     private String[] data;
 ​
     public StringServiceImpl() {
         this(DEFAULT_LENGTH);
     }
     
     public StringServiceImpl(int len) {
         if (len <= 0) {
             throw new ArrayLengthInvalidateException("当前开辟的长度有误!");
         } else {
             this.data = new String[len];
         }
     }
     
     @Override
     public void input() {
         for (int i = 0; i < this.data.length; i++) {
             this.data[i] = InputUtil.getString("请输入第" + (i + 1) + "个字符串:");
         }
     }
     
     @Override
     public String value() {
         reverse();
         return Arrays.toString(this.data);
     }
     
     private void reverse() {
         int center = this.data.length / 2;
         int head = 0;
         int tail = this.data.length - 1;
         for (int i = 0; i < center; i++) {
             String temp = this.data[head];
             this.data[head] = this.data[tail];
             this.data[tail] = temp;
             head++;
             tail--;
         }
     }
 ​
 }
 public class ArrayLengthInvalidateException extends RuntimeException {
     public ArrayLengthInvalidateException(String msg) {
         super(msg);
     }
 }
 public class ServiceFactory {
     private ServiceFactory() {
     }
 ​
     public static IStringService getInstance(int... args) {
         if (args.length == 1) {
             return new StringServiceImpl(args[0]);
         }
         return new StringServiceImpl();
     }
 ​
 }
 public class TestDemo01 {
     public static void main(String[] args) {
         IStringService stringService = ServiceFactory.getInstance();
         stringService.input();
         System.out.println(stringService.value());
     }   
 }
程序执行结果
请输入第1个字符串:
this is a test words.
请输入第2个字符串:
i am a student.
请输入第3个字符串:
i am a teacher.
请输入第4个字符串:
good good study.
请输入第5个字符串:
day day up.
[day day up., good good study., i am a teacher., i am a student., this is a test words.]

此时所有的功能都在业务接口中进行了非常完整的定义,而对于具体的子类的实现仅仅是针对所需要的业务功能做自己的处理。

案例3:输入数据排序

从键盘输入数据:“ZHANGSAN:89|LISI:90|WANGWU:95”,按照成绩的高低排序。

对于数据的排序的操作来说,再Java中是提供有一个Comparable接口的,只需要将数据设置在对象中,随后通过Arrays类的sort方法实现排序需求即可。

 public class Student implements Comparable<Student> {
     private String name;
     private double score;
 ​
     public Student() {
     }
     
     public Student(String name, double score) {
         this.name = name;
         this.score = score;
     }
     
     public void setName(String name) {
         this.name = name;
     }
     
     public String getName() {
         return name;
     }
     
     public void setScore(double score) {
         this.score = score;
     }
     
     public double getScore() {
         return score;
     }
     
     public int compareTo(Student o) {
         if (this.score > o.score) {
             return 1;
         } else if (this.score < o.score) {
             return -1;
         } else {
             return 0;
         }
     }
 }
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 ​
 public class InputUtil {
     private static final BufferedReader INPUT = new BufferedReader(new InputStreamReader(System.in));
 ​
     private InputUtil() {
     }
     
     static String getString(String prompt) {
         System.out.println(prompt);
         try {
             String value = INPUT.readLine();
             return value;
         } catch (Exception e) {
             return null;
         }
     }
     //追加字符串正则验证操作
     public static String getString(String prompt, String regex){
         while(true){
             String value = getString(prompt);
             if(value.matches(regex)){
                 return value;
             }else{
                 System.err.println("输入不合法,从新输入:");
             }            
         }
     }
     
     public static int getInt(String prompt) {
         while (true) {
             String value = getString(prompt);
             if (value != null) {
                 if (value.matches("\\d+")) {
                     return Integer.parseInt(value);
                 } else {
                     System.out.println("【错误】输入的数据必须为整型,请重新输入!");
                 }
             }
         }
     }
 ​
 }
 public interface IStudent {
     public Student[] getStudent();
 }
 import java.util.Arrays;
 ​
 public class StudentImpl implements IStudent {
     public static final String inputRegex = "([a-zA-Z]+:\\d+(\\.\\d+)?\\|?)+";
     private Student[] stus;
 ​
     public StudentImpl() {
         this.input();
     }
     
     public void input() {
         String value = InputUtil.getString("请输入字符串(ZHANGSAN:89|LISI:90|WANGWU:95):", inputRegex);
         String[] result = value.split("\\|");
         this.stus = new Student[result.length];
         for (int i = 0; i < result.length; i++) {
             String temp[] = result[i].split(":");
             this.stus[i] = new Student(temp[0], Double.parseDouble(temp[1]));
             Arrays.sort(this.stus);
         }
     }
     
     @Override
     public Student[] getStudent() {
         return this.stus;
     }
 ​
 }
 public class StudentFactory {
     private StudentFactory() {
     }
 ​
     public IStudent getInstance() {
         return new StudentImpl();
     }
 ​
 }
import java.util.Arrays;

public class TestDemo01 {
    public static void main(String[] args) throws Exception{
        IStudent student = StudentFactory.getInstance();
        System.out.println(Arrays.toString(student.getStudent()));
    }
}
程序执行结果
请输入字符串(ZHANGSAN:89|LISI:90|WANGWU:95):
zhangsan:90|lisi:85|wangwu:68|zhaoliu:77
[姓名:wangwu 分数:68.0,
姓名:zhaoliu 分数:77.0,
姓名:lisi 分数:85.0,
姓名:zhangsan 分数:90.0]

从早期的String类开始讲的时候,就一直存在这种类似的数据拆分处理操作,而后这一次是直接结合了键盘输入的形式实现了动态的数据的输入控制。

案例4:用户登陆验证

完成系统登录程序,可以通过初始化参数方式配置用户名和密码,如果没有输入用户名和密码,则提示输入用户名和密码;如果输入了用户名但是没有输入密码,则提示用户输入密码,然后判断用户名是否是 laoyang,密码是否是 123456,如果正确,则提示登录成功;如果错误,显示登录失败的信息,用户再次输入用户名和密码,连续3次输入错误后系统退出。

本程序麻烦的地方在于数据输入的一系列验证处理逻辑上,当时其他的登陆控制部分相对来说比较简单,所以首先设计核心的业务功能:根据输入进行用户名和密码的验证。

public class MaxTryCountException extends RuntimeException {
    public MaxTryCountException(String msg) {
        super(msg);
    }
}
public interface ILoginService {
    public boolean login();
}
public class LoginServiceImpl implements ILoginService{
    private String uname;
    private String upass;
    public LoginServiceImpl(String uname, String upass){
        this.uname = uname;
        this.upass = upass;
    }
    @Override
    public boolean login() {
        return "laoyang".equals(this.uname)&&"123456".equals(this.upass);
    }    
}
public class LoginFactory {
    private LoginFactory() {
    }

    public static ILoginService getInstance(String uname, String upass) {
        return new LoginServiceImpl(uname, upass);
    }
}
import javax.swing.InputMap;

public class LoginMain {
    private String[] args;
    private String userName;
    private String userPass;
    private int count;
    public LoginMain(String[] args){
        this.args = args;
        while(true){
            if(this.count >= 3){
                throw new MaxTryCountException("用户登录尝试次数过多,系统退出!");
            }
            this.handle();
            ILoginService loginService = LoginFactory.getInstance(this.userName,this.userPass);
            if(loginService.login()){
                System.out.println("【登陆成功】欢迎“laoyang”登陆访问!");
                break;
            }else{
                System.out.println("【登陆失败】错误的用户名或密码,请确认登陆信息!");
                count++;
            }
        }
    }
    public void handle(){
        if(this.args.length == 0){
            this.userName = InputUtil.getString("请输入用户名:");
            this.userPass = InputUtil.getString("请输入用户密码:");
        }else if(this.args.length == 1){
            this.userName = this.args[0];
            this.userPass = InputUtil.getString("请输入用户密码:");
        }else if(this.args.length == 2){
            this.userName = this.args[0];
            this.userPass = this.args[1];
        }
    }
}
public class TestDemo01 {
    public static void main(String[] args) {
        new LoginMain(args);
    }
}
程序执行结果
请输入用户名: laoyang
请输入用户密码: 1111
【登陆失败】错误的用户名或密码,请确认登陆信息!
请输入用户名: laoyang
请输入用户密码: 123456
【登陆成功】欢迎“laoyang”登陆访问!

案例5:投票选班长

有一个班采用民主投票方法推选班长,班长候选人共4位,每个人姓名及代号分别为“张三1;李四2;王五3;赵六4”。

程序操作员将每张选票上所填的代号(1、2、3或4)循环输入电脑,输入数字0结束输入,然后将所有候选人的得票情况显示出来,并显示最终当选者的信息,具体要求如下:

①要求用面向对象方法,编写学生类 Student,将候选人姓名、代号和票数保存到类 Student中,并实现相应的 getxxx和setxxx方法。

②输入数据前,显示出各位候选人的代号及姓名(提示,建立一个候选人类型数组)。

③循环执行接收键盘输入的班长候选人代号,直到输入的数字为0,结束选票的输入工作。

④在接收每次输入的选票后要求验证该选票是否有效,即如果输入的数不是0、1、2、3、4这5个数字之一,或者输入的是串字母,应显示出错误提示信息“此选票无效,请输入正确的候选人代号!”,并继续等待输入。

⑤输入结束后显示所有候选人的得票情况,如参考样例所示

⑥输出最终当选者的相关信息,如参考样例所示

1:张三[0票]

2:李四[0票]

3:王五[0票]

4:赵六[0票]

请输入班长候选人代号(数字0结束):1

请输入班长候选人代号(数字0结束):1

请输入班长候选人代号(数字0结束):1

请输入班长候选人代号(数字0结束):1

请输入班长候选人代号(数字0结束):2

请输入班长候选人代号(数字0结束):3

请输入班长候选人代号(数字0结束):4

请输入班长候选人代号(数字0结束):5

此选票无效,请输入正确的候选人代号

请输入班长候选人代号(数字0结束): hello

此选票无效,请输入正确的候选人代号!

请输入班长候选人代号(数字0结束):0

1:张三[4票]

2:李四[1票]

3:王五[1票]

4:赵六[1票]

投票最终结果:张三同学,最后以4票当选班长!

由于优选人信息固定,所以可以考虑通过对象数组的形式进行所有候选人信息保存。

public class Student implements Comparable<Student>{
    private long id;
    private String name;
    private int count;
    public Student(long id, String name, int count){
        this.id = id;
        this.name = name;
        this.count = count;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return "【候选人】编号:" + this.id + "\t姓名:" + this.name + "\t票数:" + this.count;
    }
    @Override
    public int compareTo(Student o) {
        return o.count - this.count;
    }
}
public interface IVoteService {
    public void start();
    public Student[] show();
    public Student result();
}
public static int getInt(String prompt, String errorMsg) {
        while (true) {
            String value = getString(prompt);
            if (value != null) {
                if (value.matches("\\d+")) {
                    return Integer.parseInt(value);
                } else {
                    System.out.println(errorMsg);
                }
            }
        }
    }
import java.util.Arrays;

public class VoteServiceImpl implements IVoteService {
    private Student[] stus = new Student[] { new Student(1, "张三", 0), new Student(2, "李四", 0), new Student(3, "王五", 0),
            new Student(4, "赵六", 0) };

    public VoteServiceImpl() {
    
    }
    
    @Override
    public void start() {
        boolean flag = true;
        while(flag){
            int choose = InputUtil.getInt("请输入班长候选人代号(数字0结束):", "此选票无效,请输入正确的候选人代号!");
        switch (choose) {
        case 0:
        flag = false;
            break;
        case 1:
            this.stus[0].setCount(this.stus[0].getCount() + 1);
            break;
        case 2:
            this.stus[1].setCount(this.stus[1].getCount() + 1);
            break;
        case 3:
            this.stus[2].setCount(this.stus[2].getCount() + 1);
            break;
        case 4:
            this.stus[3].setCount(this.stus[3].getCount() + 1);
            break;
        default:
            System.out.println("此选票无效,请输入正确的候选人代号!");
        }
        }
    }
    
    @Override
    public Student[] show() {
        return this.stus;
    }
    
    @Override
    public Student result() {
        Arrays.sort(this.stus);
        return this.stus[0];
    }
}
public class StudentFactory {
    private StudentFactory(){}
    public static IVoteService getInstance(){
        return new VoteServiceImpl();
    }
}
public class VoteMain {
    private IVoteService voteService;
    public VoteMain(){
        this.voteService = StudentFactory.getInstance();
        this.printStudentInfo(this.voteService.show());
        System.out.println("=================开始班长选举==================");
        this.voteService.start();
        System.out.println("=================班长选举结束==================");
        this.printStudentInfo(this.voteService.show());
        System.out.println("=================班长选举结果==================");
        Student result = this.voteService.result();
        System.out.println("【投票结果】" + result.getName() + "同学,最后以" + result.getCount() + "票当选班长!");
    }
    private void printStudentInfo(Student[] stus){
        for(Student stu : stus){
            System.out.println(stu);
        }
    }
}
public class TestDemo01 {
    public static void main(String[] args) {
        new VoteMain();
    }
}
程序执行结果
【候选人】编号:1 姓名:张三 票数:0
【候选人】编号:2 姓名:李四 票数:0
【候选人】编号:3 姓名:王五 票数:0
【候选人】编号:4 姓名:赵六 票数:0
开始班长选举
请输入班长候选人代号(数字0结束):
1
请输入班长候选人代号(数字0结束):
1
请输入班长候选人代号(数字0结束):
1
请输入班长候选人代号(数字0结束):
2
请输入班长候选人代号(数字0结束):
3
请输入班长候选人代号(数字0结束):
4
请输入班长候选人代号(数字0结束):
5
此选票无效,请输入正确的候选人代号!
请输入班长候选人代号(数字0结束):
0
班长选举结束
【候选人】编号:1 姓名:张三 票数:3
【候选人】编号:2 姓名:李四 票数:1
【候选人】编号:3 姓名:王五 票数:1
【候选人】编号:4 姓名:赵六 票数:1
班长选举结果
【投票结果】张三同学,最后以3票当选班长!

面对于所有复杂的程序模型介绍,核心的关键是要进行问题的拆分,而后根据拆分的结果进行功能的设计,最终完成需要的项目的开发目的。温馨提示:此处内容需要登录或VIP权限才能查看!请联系管理员升级您的用户权限!


留下一个回复