天天看点

北理工Java实验2.4(文件字符流读入)

java编程时经常会遇到读入文件内容,因此这部分内容有必要掌握,以下就java实验项目对文件读入部分进行总结(项目源码地址:https://github.com/HuangFuGui/Java/tree/master/javaExperiment2.4),欢迎指点。

问题需求:

You are asked to write a student marks program that reads in a file of student marks, then calculates the mean of these marks and, finally, outputs these values to standard output.

Marks are stored in a file called: cs1marks.dat in the format of

Smith 85

Jones 72

You are given the class StudentRecord (see attachment), which defines an object that contains a student name and mark. The class has methods for getting the name and mark from the StudentRecord.

You are given the incomplete driver class MarksMain (see attachment). This driver creates a new MarksFile object and reads the MarksFile via the readFile method (do not worry how the file is read in yet). For this part, the only thing you need to know is that the readFile method returns a Vector of StudentRecord objects.

1) Complete the indicated section of MarksMain, which prints to standard out:

· the student results stored in the Vector marks, and

· the average of the marks.

2) Examine the skeleton of the MarksFile class(see attachment). There are two methods that must be implemented: the constructor MarksFile and the method readFile.

2.1) The MarksFile constructor, takes a filename as an argument and creates an input character stream to the file. This stream is assigned to the variable fs.

Note that the type of fs is not given. What is the correct type for the variable fs?

2.2) The readFile method reads in each line of data from the data file and creates a new StudentRecord with a name and mark. It then stores this new StudentRecord in the Vector results. When all the values have been read and stored, it returns the Vector results. Complete the missing section to read in the values from the file and store them in results.

将指定文件的内容读取并在控制台中打印,文件中的内容为学生姓名,学生成绩,格式为:

Smith 85

Jones 72

Mary 99

注意:姓名与成绩之间为Tab键

项目结构:

北理工Java实验2.4(文件字符流读入)

StudentRecord类:

package marksprogramPackage;

class StudentRecord {
    private String studentName;
    private int mark;

    public StudentRecord(String name, int value) {
        studentName = name;
        mark = value;

    }

    public String getName() {
        return studentName;
    }

    public int getMark() {
        return mark;
    }
}           
  1. StudentRecord类相当于实体类。

MarksMain类:

package marksprogramPackage;

import java.util.Iterator;
import java.util.Vector;
import java.io.*;

public class MarksMain {
    public static void main (String[] args){
        final String fileName = "cs1marks.dat";
        Vector marks; // marks is a Vector of Mark objects
        StudentRecord entry;
        int averageSum = 0;
        MarksFile cs1MarksFile = new MarksFile(fileName);

        // marks is a Vector of StudentRecord objects
        marks = cs1MarksFile.readFile();


        // print out each student's mark on a separate line in the
        // format: Student Name <tab> mark
        // at the end print out on a separate line the average (mean) mark in the
        // format: Average: avg mark

        //FILL IN THE CODE HERE 
        for(int i=0;i<marks.size();i++){

            entry = (StudentRecord) marks.get(i);
            System.out.println(entry.getName()+"\t"+entry.getMark());
            averageSum +=entry.getMark();

        }
        System.out.println("Average: "+averageSum/marks.size());
    }
}           
  1. fileName就是要读取的文件名;
  2. Vector是一个容器,在这里是用于存储学生分数的容器;
  3. for循环就是很简单的读取Vector容器的内容,并且从这里可以看到marks里面有很多学生成绩的Object,那这是从哪来的呢?
  4. 显然,marks = cs1MarksFile.readFile();中的readFile()方法返回了学生成绩的Object;
  5. 那cs1MarksFile又是什么呢?MarksFile cs1MarksFile = new MarksFile(fileName);又是干嘛的?

MarksFile类:

package marksprogramPackage;

import java.util.*;
import java.io.*;

public class MarksFile {

    //InputStreamReader 将字节流转换为字符流。是字节流通向字符流的桥梁。
    private InputStreamReader fs;

    public MarksFile(String filename) {
        // creates an input character stream to the file and assign to variable
        // fs
        try {
            fs = new InputStreamReader(new FileInputStream(filename));
            //读取字节流: InputStream in = new FileInputStream(filename)
        } catch (Exception e) {
            System.err.println("File not found.");
        }
    }

    public Vector<StudentRecord> readFile() {

        String line;
        Vector<StudentRecord> v = new Vector<StudentRecord>();
        StudentRecord sr;

        // create a buffered reader so we can read in a line
        BufferedReader inFile = new BufferedReader(fs);

        try {
            while ((line = inFile.readLine()) != null) {
                char[] arr = line.toCharArray(); //将缓冲的字符流转换为字符数组存起来方便后序处理
                char[] arr2 = new char[10];
                char[] arr3 = new char[10];
                int i, j;
                String name;
                String age;
                for(i = 0; i < arr.length && arr[i] != '\t'; ++i);
                for(j = 0; j < i; ++j){
                    arr2[j] = arr[j];
                }
                name = String.valueOf(arr2);    //字符串类
                name = name.substring(0, i);    //[0,i)
                for(j = i + 1; j < arr.length; ++j){
                    arr3[j - i - 1] = arr[j];
                }
                age = String.valueOf(arr3);
                age = age.substring(0, j - i - 1);
                sr = new StudentRecord(name, Integer.parseInt(age)); //int包装类Integer将字符串转换为基本数据类型int
                v.add(sr);  //向容器添加学生成绩对象

            }

        } catch (IOException e) {

            System.err.println("IO exception");
        }
        // close the file
        finally{
            try {
                inFile.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return v;
    }
}           
  1. 首先MarksFile类有一个有参的构造器,参数为filename,从代码上看,这个有参的构造器用于对成员变量InputStreamReader赋值。InputStreamReader将字节流转换为字符流,是字节流通向字符流的桥梁。而 //读取字节流: InputStream in = new FileInputStream(filename);就是读取文件内容使其成为字节流。因此,这部分的功能就是产生filename对应的文件的输入字符流并赋值给InputStreamReader。
  2. readFile()方法返回的是一个存储了学生成绩的容器。BufferedReader是”缓冲读取器”的意思,从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。接下来关于数据处理的代码部分应该比较简单了,注释也写得比较详细。

测试:

北理工Java实验2.4(文件字符流读入)

成功读取文件内容并在控制台输出!