Java如何将对象输入流读入ArrayList?

6
下面的方法应该将二进制文件读入一个arrayList中,但是出现了java.io.EOFException异常:

at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2553)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1296)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at .... Read(Tester.java:400) 
at .... main(Tester.java:23)

主函数中的第23行只是调用该方法,第400行是下面的while循环。有什么想法吗?

private static void Read() {
    try {
        ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("/file.bin"));
        while (objIn.readObject() != null) {
            list.add((Libreria) objIn.readObject());
        }
        objIn.close();
    } catch(Exception e) {
        e.printStackTrace();
    }
}
4个回答

9
根据其他答案,您在循环中读取两次。您的另一个问题是空值测试。readObject()仅在写入空值时返回null,而不是在EOS时返回null,因此使用它作为循环终止测试没有太多意义。正确终止readObject()循环的方法是:
catch (EOFException exc)
{
 in.close();
 break;
}

@ash,你不能这样做。你要么在循环内部捕获EOFException并且跳出循环,要么在外部捕获并省略break语句,显然只能二选一。 - user207421
@David,我对任何将读取顺序文件时的EOF排除在明显异常情况之外的“异常”定义都不感兴趣。在这种情况下,由于null是一种带内值,API在EOF时没有其他行为方式。readInt()、readShort()、readUTF()及其类似方法同样适用。 - user207421
1
@EJP我同意这是使用API的方法。我只是觉得不幸的是,每个想要读取的文件最终都会发生的文件结束,被称为“异常”。相反,像in.isEndOfFile()这样的方法可能会很好。无论如何,使用我们今天拥有的API,你的答案是正确的。 - David Koelle
1
@David 那个建议行不通。在调用isEndOfFile()之后,文件可能会继续增长。在TCP中,除了尝试读取之外,没有其他方法来检测EOS。因此,EOS必须是读取的返回值或副作用,如果没有可用的带外返回值,则不能是返回值:在具有结果参数的语言中,它可以是结果参数;在Java中,它必须是异常。这是无法避免的。 - user207421
@ECP 我明白你的意思。谢谢你的解释! - David Koelle
显示剩余2条评论

7
问题在于您在循环中调用了两次readObject()。请尝试使用以下代码替换:
MediaLibrary obj = null;
while ((obj = (MediaLibrary)objIn.readObject()) != null) {
     libraryFromDisk.add(obj);
}

在 while 循环中仍然遇到相同的错误。我尝试了类似的代码: Object obj = null; while ((obj = objIn.readObject()) != null) { if (obj instanceof MediaLibrary) { MediaLibrary list = (MediaLibrary) obj; libraryFromDisk.add(list); } } - ash

4

您正在while测试中读取一个对象:

while (objIn.readObject() != null)

那么你正在读取下一个对象:

libraryFromDisk.add((MediaLibrary) objIn.readObject());

因此,在一次迭代中,您应该只读取一个对象

private static void Load() {
    try {
        ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("/file.bin"));
        Object object = objIn.readObject();
        while (object != null) {
           libraryFromDisk.add((MediaLibrary) object);
           object = objIn.readObject();

        }
        objIn.close();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

在 while 循环中仍然遇到相同的错误。我尝试过类似的方法:Object obj = null; while ((obj = objIn.readObject()) != null) { if (obj instanceof MediaLibrary) { MediaLibrary list = (MediaLibrary) obj; libraryFromDisk.add(list); } } - ash
也许 objIn 中的数据是另一个问题。在 ObjectInputStream 的 Javadoc 中,它说“原始读取将抛出 EOFExceptions”。objIn 包含原始数据吗?(而不是类的实例) - Jihed Amine
它不包含原始数据,或者至少不应该包含。这是我用来在单独的方法中编写文件的循环。 for(MediaLibrary item: library) { objOut.writeObject(item); } - ash

0
你可以试试这个。祝你好运!
private static void Load() {
try {
    ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("/file.bin"));
    boolean check=true;
    while (check) {

try{
object = objIn.readObject();
libraryFromDisk.add((MediaLibrary) object);
}catch(EOFException ex){
check=false;
}

    }
    objIn.close();
} catch(Exception e) {
    e.printStackTrace();
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接