2

我正在做关于 java I/O 数据的作业,问题是我不允许使用对象序列化从二进制文件加载数据。

以下是作业要求:

持久性,将对象写入文件和从文件中读取对象(文本格式)

• All objects should be written to a single file in a text format
• All objects should be read form the same file
• You should use JFileChooser

我有 3 个课程:UnitAssessmentTask

该类Assessment是抽象的,而IndividualAssessment&GroupAssessment 是具体的子类。

Unit有一个集合Assessment并且Assessment有一个集合Tasks.

我可以将所有数据保存到一个文本文件中,FileWriter但我不知道如何将文本文件的每一行读入正确的Assessment类。

我的意思是你如何识别哪条线是用于IndividualAssessmentGroupAssessment类的。

这是我尝试过的代码,但它不起作用:

BufferedReader bf = new BufferedReader(file);
While (bf.readLine != null){
    Unit u = new Unit(bf);
    diary.add(u);
    try{
        Assessment a = new IndividualAssessment(bf);
    } catch (IOException ex){
        Assessment a = new GroupAssessment(bf);
            }
    u.add(a);
    Task t = new Task(bf);
    a.add(t);
4

3 回答 3

1

您可能应该从将读取的行的内容存储在 String 对象中开始。所以它看起来像这样:

String line = bf.readLine();
while(line != null) {
    // Add code to look at your line to figure out what kind of object it 
    // represents.   For example you could add a one character prefix to each 
    // line when you write it to specify which object it is ('U', 'A' or 'T').
    // Based on that, you can call a constructor of the appropriate object that
    // takes a String as input. Then let the constructor deal with parsing the
    // line for the object it represents. This way you don't end up with some
    // massive parsing routine.

    char code = line.charAt(0);
    if(code == 'T') {
        Task task = new Task();
        task.initFromString(line.sustring(1));
        ... Do something with your task
    }
    else if(code == ...) {
    }

    line = bf.readLine();    // Read the next line
}

定义所有对象都应该实现的一些接口:

public interface TextExportable {
    public char getClassIdentifier();
    public void initFromString(String s);
}

我不确定您的对象是什么样的,但例如:

public class Task implements TextExportable {
    private String name;

    public Task() {} // For the pseudo-serialization

    public Task(String name) { // For creating the object by hand
        this.name = name;
    }

    public char getClassIdentifier() {
        return 'T';
    }

    public String toString() {
        return getClassIdentifier()+name;
    }

    public void initFromString(String line) {
        this.name = line;
        // Here, you would need extra parsing if you have more than one attribute
        // and dissect the line
    }
}
于 2012-05-25T16:53:36.067 回答
0

将 aBufferedReader作为构造函数的参数是一种非常规的方法。BufferedReader在您的实例中是交付模型数据的工具。而且您的模型数据应该与您的用例有关,而不是关于您如何将其存储在磁盘上,因此它应该足够抽象。因此,相反,我将在您的每个模型类上都有一个默认构造函数,然后可能是一个可用于初始化模型类的所有/某些字段的构造函数。

处理文件接口的一种方法是创建文件读取器/写入器实用程序,可以将数据从文件加载/保存到文件。如果你的类层次结构的顶部是Unit那么我会这样:

Unit loadFromFile(String filename) {
   // read unit, assessments etc in a format you choose, build the model and return it
   ...
}

void saveToFile(String filename) {
   // write you model to a file
   ...
}

如果我是你,我会使用JSON作为我的数据格式。它是可读的并且易于调试。

我希望这有帮助。

于 2012-05-25T17:10:33.243 回答
0

除了接受的答案之外,我想补充一点,一种干净的解析方法是遵循解释器模式

因此,假设使用 bnf 的语法如下:

<Unit>        ::= <Name>[<Assessments>]
<Assessments> ::= <Assessment> | <Assessment> <Assessments>
<Assessment>  ::= <Name>:<Type>[<Tasks>]
<Tasks>       ::= <Task> | <Task>,<Tasks>
<Name>        ::= <String>
<Type>        ::= Group | Ind

你可能会写这样的东西来解析它——我把它作为一个练习来编写所Expression使用的类。

try {
    BufferedReader br = new BufferedReader(new FileReader("File.txt"));
    try {
        String unit;
        while ((unit = br.readLine()) != null) {
            String unitName = unit.substring(0, unit.indexOf('['));
            String assessments = unit.substring(unit.indexOf('[') + 1,
                            unit.lastIndexOf(']'));
            List<AssessmentExpression> aes = new ArrayList<AssessmentExpression>();
            while (!assessments.equals("")) {
                String assessmentName = assessments.substring(0,
                                assessments.indexOf(':'));
                String assessmentType = assessments.substring(
                                assessments.indexOf(':') + 1,
                                assessments.indexOf('['));
                String tasks = assessments.substring(
                                assessments.indexOf('[') + 1,
                                assessments.indexOf(']'));
                List<String> taskList = Arrays.asList(tasks.split(","));
                aes.add(new AssessmentExpression(assessmentName,
                                assessmentType, taskList));
                assessments = assessments.substring(assessments.indexOf(']')+1);
            }

            Unit u = new UnitExpression(unitName, aes).interpret();
        }
    } finally {
        br.close();
    }
} catch (IOException e) {
    e.printStackTrace();
}
于 2012-05-26T08:46:46.103 回答