追加数据后,ObjectInputStream 未读取完整文件

问题描述

我正在编写一个小程序,用于在 ArrayList 中插入客户详细信息并将其写入文件

问题在于 ObjectOutputStream 我能够通过转动 FileOutputStream("",true)文件中附加数据。但是当我尝试使用 ObjectInputStream 读取数据时,它只读取第一次插入的数据。但是正在将数据添加文件中。

这是代码 -

public void insertCustomer() throws IOException 
{       
        Customer1=new customerDetails("1","Moeen4","654654","asdf","coding","student","65464","3210");
        Customer3=new customerDetails("3","Moeen5","888888","student2","321022");
        Customer4=new customerDetails("4","Moeen6","7890");
        
        _list=new ArrayList<customerDetails>();
        _list.add(Customer1);
        _list.add(Customer3);
        _list.add(Customer4);
        
        customersList cl=new customersList();
        
        cl.WriteObjectToFile(files._customers,_list);
        
        ArrayList<customerDetails>li=new ArrayList<customerDetails>();
        li= (ArrayList) cl.ReadobjectFromFile(files._customers);           
        for(int i=0;i<li.size();i++)
        {   System.out.println(li.size());
            System.out.println(li.get(i).Id);
            System.out.println(li.get(i).name);
            System.out.println(li.get(i).annual_Salary);
            System.out.println(li.get(i).Company);
            System.out.println(li.get(i).dateOfBirth);
            System.out.println(li.get(i).phone_Number);
        }
    }


public void WriteObjectToFile(String filepath,Object serObj) {       
    try {
        
        FileOutputStream fileOut = new FileOutputStream(filepath,true);
        ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
        objectOut.writeObject(serObj);
        objectOut.close();
        System.out.println("The Object  was succesfully written to a file");

    } catch (Exception ex) {
        ex.printstacktrace();
    }
}

public Object ReadobjectFromFile(String filepath) {      
    try {

        FileInputStream fileIn = new FileInputStream(filepath);
        ObjectInputStream objectIn = new ObjectInputStream(fileIn);

        Object obj = objectIn.readobject();
        objectIn.close();
        System.out.println("The Object has been read from the file");
        
        return obj;

    } catch (Exception ex) {
        ex.printstacktrace();
        return null;
    }
}

解决方法

真正的问题是:

  FileOutputStream fileOut = new FileOutputStream(filepath,true);
  ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
  objectOut.writeObject(serObj);

您不能像这样附加到现有的序列化。如果在尝试读取附加到预先存在的(非空)文件的任何对象时确实遇到异常。

虽然有一个技巧/技巧可以让您附加对象;见Appending to an ObjectOutputStream。 (这个技巧涉及抑制对象流标头的写入。最容易通过覆盖执行此操作的方法来完成。)

另一种方法是在 ObjectOutputStream 调用之间保持 writeObject 打开。但是,有些用例是不可能的。

请注意,这两种方法之间存在语义差异。解释它的最好方法是,第一个行为就像每次编写对象时都调用了 reset() 一样;请参阅javadoc


关于您的示例的另一件事要注意的是,您的阅读器代码仅读取一个对象。如果要读取多个对象,则需要循环调用readObject。这只有在您使用上面的技巧/技巧来避免编写虚假标题时才有效。

,

正如所建议的那样,代码仅读取第一个对象,您需要使用循环从多次写入中读取所有对象。

但是 -

如果您更改上述代码,即 ReadObjectFromFile 以使用循环,这将导致 StreamCorruptedException: invalid type code: ACObjectOutputStream constructor 将序列化流标头写入 OutputStream 即文件,当它使用 new ObjectOutputStreamnew FileOutputStream(filepath,true) 关闭并重新打开时,将是一个新标头写在追加点,所以你会得到一个异常,因为在文件的开头只需要一次头

这将需要处理例如

  • 在持续时间内使用相同的 ObjectOutputStream
  • 覆盖 java.io.ObjectOutputStream.writeStreamHeader() 以说明追加到文件
  • 改变方法并使用 List<List<Object>>,您可以整体读取、添加、写入。

循环示例将抛出异常,除非更改 ObjectOutputStream 方法

public Object ReadObjectFromFile(String filepath) {
    
    List<List<Object>> objects = new ArrayList<>();
    
    FileInputStream fileIn = new FileInputStream(filepath);
    ObjectInputStream objectIn = new ObjectInputStream(fileIn);
    
    try {
        while (true) {
            List<Object> obj = (List<Object>) objectIn.readObject();
            // This will throw StreamCorruptedException: invalid type code: AC
            objects.add(obj);
            System.out.println("The Object has been read from the file");                
        }
    } catch (EOFException ex) {
        // ENDS WHEN ALL READ
    } finally {
        fileIn.close();
        objectIn.close();
    }
    
    return objects;
}

Sudo 代码 List<List<Object>> 方法 -

public void readAndWrite() {
    List<Object> customer = List.of(new CustomerDetails(...),new CustomerDetails(...),new CustomerDetails(...));
    
    List<List<Object>> objects = readFromFile("existing-customer-file.txt");

    objects.addAll(customer);
    
    writeObjectToFile(objects);
}