ObjectOutputStream 根据我打开流的方式不同地写入相同的实例

ObjectOutputStream writes same instances differently depending on how i open stream

由于未知原因,写入同一个 objectOutputStream 的实例和单独写入的实例(如果我在每次迭代中打开 objectOutputStream)都会创建两个不同的文件。

ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filepath1));
for (User user : users)
{
    objectOutputStream.writeObject(user);
}

objectOutputStream.close();

for (User user : users)
{
    objectOutputStream = new ObjectOutputStream(new FileOutputStream(filepath2, true));
    objectOutputStream.writeObject(user);
    objectOutputStream.close();
}

所以当我像这样循环读取文件时,它只对第一个文件有效。

for( int i = 0; i< users.length; i++)
{
    readUsers[i] = (User)objectInputStream.readObject();
}

读取第二个文件给了我一个正确读取的用户,然后是异常 java.io.StreamCorruptedException: invalid type code: AC。 我已经检查了这些文件的内容,第二个记录的每条记录的开头似乎都有过多的数据(它几乎是第一个 space 的两倍)。 那么如何结合第二种方式将实例写入文件并在之后在一个简单的循环中读取它们呢?

您无法轻松将来自两个个不同ObjectOutputStreams的数据写入同一个文件.

含义:

  • 要么你想写入不同的文件要么
  • 您使用 same ObjectOutputStream 将 所有 您的对象写入该文件。

这是二进制数据结构,具有隐式布局,相应的协议根本不期望另一个 序列化字节流在第一个对象序列被完全处理后出现在文件中 - 除非你“按摩”进入该文件的确切内容(有关详细信息,请参阅其他答案)。

Java 序列化,由 Object{Output,Input}Stream 实现,除了每个对象的元数据和数据外,还有一个 stream 头,只出现一次,不会出现对于每个对象。通常在一个文件中,这相当于一个文件头。 如果你想将多个流放在一个文件中,必须自己管理流边界:

//nopackage
import java.io.*;

public class SO71319428MultipleSerial {
  public static void main (String[] args) throws Exception {
    User[] a = { new User("Alice",1), new User("Bob",2), new User("Carol",3) };
    for( User u : a )
      try( ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(filename,true)) ){
        oo.writeObject(u);
      }
    System.out.println("reading "+new File(filename).length());
    try( InputStream fi = new FileInputStream(filename) ){
      for( int i = 0; i < 3; i++ ){
        ObjectInputStream oi = new ObjectInputStream(fi);
        System.out.println( oi.readObject() );
        // DON'T close because that closes the underlying FileInputStream; just leak instead
      }
    }
  }
  public static String filename = "SO71319428.out";

  static class User implements Serializable {
    String name; int id;
    public User(String name, int id){ this.name=name; this.id=id; }
    public String toString(){ return name+" is #"+id; }
  }
}
->
reading 283
Alice is #1
Bob is #2
Carol is #3

这不如 single-stream(具有多个对象)方法灵活,因为它允许您编写可以识别类型 结束的任何对象序列在没有任何帮助的情况下阅读;使用 multiple-stream 方法 您的代码 必须能够确定流何时结束并需要重新启动。