问题描述
我正在编写一个小程序,用于在 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: AC
。 ObjectOutputStream
constructor 将序列化流标头写入 OutputStream
即文件,当它使用 new ObjectOutputStream
和 new 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);
}