Java基础IO流综合实例


一,问题描述 

 有五个学生,每个学生有3门课的成绩
 从键盘输入以上数据(包括姓名,三门课成绩)
 输入的格式:如:zhangsan,30,40,50计算出总成绩
 并把学生的信息和计算出的总分数从高到底顺序存放在磁盘文件“Stud.txt”中

二,思路

1、首先我们需要一个学生对象(Student),再需要一个容器来存储这些学生对象,由于学生对象需要按总分数排序,所以需要一个能排序的容器,这里就使用了TreeSet。

2、学生对象不具备比较性,因此学生对象需要实现一个比较器接口,这里就使用了Comparable接口。

3、学生对象被放到容器中,如何区分是不是同一个学生呢,这时就不能使用默认的equals方法了,因此学生类必须覆盖Object类的equals方法来定义自己的区分方法。由于TreeSet放入对象时,先调用该对象的hashCode()方法,与容器中已存在的对象的hashCode做比较,如果相同,就还要调用一次该对象的equals方法来保证元素的唯一性,否则就不调用equals方法,而直接添加对象了。为了更好保证元素的唯一性,我们需要覆盖hashCode()方法。

4、输入学生信息时,由于输入流的来源是键盘,键盘输入的字符,所有就用到了Reader类,为了更高效,就使用了BufferedReader类。这个类接收一个InputStreamReader对象作为构造器参数,而InputStreamReader需要一个InputStream对象作为其构造参数,因此就使用了System.in对象,它是InputStream类型,称为“标准”输入流,通常对应的就是键盘输入。把学生信息写入到磁盘文件就使用了BufferedWriter来达到高效写入。
三,具体代码实现
import java.io.*;
import java.util.*;
class Student implements Comparable<Student> {
private String name;
private int ma, cn, en;
private int sum;


Student(String name, int ma, int cn, int en) {
this.name = name;
this.ma = ma;
this.cn = cn;
this.en = en;
sum = ma + cn + en;
}

public int compareTo(Student s) {       //实现接口所要求的方法,以便按我们所需要的方式排序学生对象
int num = new Integer(this.sum).compareTo(new Integer(s.sum));//比较两个学生对象的总分数,以便按总分排序
if (num == 0)
return this.name.compareTo(s.name);  //如果总分数相同,就比较姓名,次要条件就会以姓名排序
return num;
}

public String getName() {
return name;
}

public int getsum() {
return sum;
}

public int hashCode() {            // 覆盖了默认的hashCode()方法以保证学生的唯一性
return name.hashCode() + sum * 78;
}

public boolean equals(Object obj) {
if (!(obj instanceof Student))        //判断传入的参数是否为Student类型,不是就会抛出类转型异常
throw new ClassCastException("类型不匹配");
Student s = (Student) obj;
return this.name.equals(s.name) && this.sum == s.sum;   //比较两个学生对象的姓名和总分数,相同则返回true,否则为false
}

public String toString() {   //自定义自己的打印学生对象方法
return "student[" + name + "," + ma + "," + cn + "," + en + "]";
}
}


class StudentInfoTool {//收集学生信息的工具来

public static Set<Student> getStudents() throws Exception {
return getStudents(null);
}

 //从键盘获取学生信息,并存入到TreeSet集合中,该方法返回一个包含学生对象的Set集合
public static Set<Student> getStudents(Comparator<Student> cmp)   //传入一个比较器以便按需排序

 throws Exception {  //为简化代码,就把异常直接抛出了,但实际开发中不能这么做
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System.in));
String line = null;

Set<Student> stus = null;
if(cmp==null) stus=new TreeSet<Student>();
else stus=new TreeSet<Student>(cmp);

while ((line = bufr.readLine()) != null) {
if ("over".equals(line))    //输入over就结束输入学生信息
break;
String[] info = line.split(","); //把输入的一行数据串按','切割以便获取姓名和各们课成绩数据
Student stu = new Student(info[0], Integer.parseInt(info[1]),
Integer.parseInt(info[2]), Integer.parseInt(info[3]));//把获取的学生信息用来创建一个具体的学生对象


stus.add(stu);//把学生对象添加到集合中
}


bufr.close();//关闭输入流,释放资源
return stus;
}

//把存储有学生对象的集合写入到文件中
public static void write2File(Set<Student> stus) throws Exception {
BufferedWriter bufw = new BufferedWriter(new FileWriter("Stuinfo.txt"));
for (Student stu : stus) {
bufw.write(stu.toString() + "\t");
bufw.write(stu.getsum() + "");
bufw.newLine();//写入一个行分隔符
bufw.flush();//刷新该流的缓冲,即把内存中的数据写入到文件中
}

bufw.close();
}

}


class StudentInfoTest {
public static void main(String[] args) throws Exception {

//上面Student类实现了Comparable接口后,就会按总分数的自然顺序排序,即从低到高。但题目要求的是从高到低,而Collections的reverseOrder()方法就会强行逆转这个自然顺序,即从高到低了
       Comparator<Student> cmp=Collections.reverseOrder();
Set<Student> stus = StudentInfoTool.getStudents(cmp); //传入强行逆转后的比较器
StudentInfoTool.write2File(stus);//把按总分排序的学生信息写入的文件中
}
}

扫描二维码关注公众号,回复: 2577729 查看本文章

四、总结

        本题涉及到内容总结

 1、对象,首先需要建立学生对象;

 2、集合,存储对象并比较对象

 3、IO流:(1)缓冲区:为了提高效率使用了BufferedReader、BufferedWriter

                   (2) 输入流:InputStream对应键盘输入

                   (3)输出流:FileWriter

猜你喜欢

转载自blog.csdn.net/u011638706/article/details/40295421