有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java从文件反序列化多个对象而不使用while(true)

我有一段代码,它将文件中的多个对象反序列化。如何避免使用一段时间(正确)

ObjectInputStream in = new ObjectInputStream(new FileInputStream(
        filename));

while (true) {
    try {
        MyObject o = (MyObject) in.readObject();
        // Do something with the object
    } catch (EOFException e) {
        break;
    }
}

in.close();

共 (3) 个答案

  1. # 1 楼答案

    How can i avoid using a while(true)?

    你不能

    更重要的是,你为什么认为你想这么做

    这是摇尾巴的典型例子。抛出EOFEException以指示流的结束。因此,你必须抓住它,并且你必须循环直到它被抛出,因此你必须使用while(true)或它的一个同源词

    例外情况认为警察会让你预先准备一个对象计数,采取奇怪的立场,外部数据结构应该设计成适合编码者的恐惧症,并且忽略你可能事先不知道,或者可能需要改变主意,或者可能需要提前退出;或者让您编写一个null作为流结束标记,忽略它会阻止将null用于任何其他目的;在这两种情况下,我们都忽略了这样一个事实,即API已经被设计为抛出EOFEException,并且已经按照它的工作方式工作了,因此您已经需要相应地编写代码

  2. # 2 楼答案

    我所建议的代码让您可以非常轻松地序列化和反序列化多个对象,而不会出现任何问题,并且避免了可怕的(在我看来)错误:

    public class EntityClass implements Serializable{
    private int intVal;
    private String stringVal;
    
    public EntityClass(int intVal, String stringVal) {
        this.intVal = intVal;
        this.stringVal = stringVal;
    }
    
    @Override
    public String toString() {
        return "EntityClass{" +
                "intVal=" + intVal +
                ", stringVal='" + stringVal + '\'' +
                '}';
    }
    
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        EntityClass a = new EntityClass(1, "1");
        EntityClass b = new EntityClass(2, "2");
        EntityClass c = new EntityClass(3, "3");
    
        ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream("out"));
    
        stream.writeObject(a);
        stream.writeObject(b);
        stream.writeObject(c);
    
        stream.close();
    
        ObjectInputStream streamRead = new ObjectInputStream(new FileInputStream("out"));
    
        EntityClass[] entities = new EntityClass[3];
        int cont  = 0;
    
        try {
            while (streamRead.available() >= 0) {
                entities[cont] = (EntityClass) streamRead.readObject();
                System.out.println(entities[cont]);
                cont++;
            }
        } catch (EOFException exp) {
    
        } finally {
            streamRead.close();
        }
    }
    
    }
    
  3. # 3 楼答案

    您应该在每个对象之前写入集合(具有大小)或标记:

    try {
      for (;in.readBoolean();) {
        MyObject o = (MyObject) in.readObject();
    
      }
    } catch (EOFException e) {
      // ...
    }
    

    当你写你的对象时,在前面写一个布尔值(如果我记得很清楚的话,它需要1个字节):

    for (MyObject o : iterable) {
      out.writeBoolean(true);
      out.writeObject(o);
    }
    out.writeBoolean(false);
    

    如果iterable是集合或映射,则可以使用默认序列化:

    out.writeObject(iterable); // default collection serialization
    

    此外,不要捕获每个项目的异常,而是全局捕获它(尤其是EOFEException!):出于性能方面的原因,它更好

    我不知道您是否使用Java 7,但您的代码+我的for循环可以这样编写:

    try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(     filename))) {
      for (;in.readBoolean();) {
        MyObject o = (MyObject) in.readObject();
    
      }
    } catch (EOFException e) {
      // ...
    }
    // no need to close, the try-with-resources do the job for you.