对于今天关于序列化的第二篇文章感到抱歉,解决一个问题导致另一个问题。
作为州的状态 - Java - Serialization - NotSerializableException Issue - 我有一个包含以下类的项目
Student.java
StudentsCollection.java
学生创建我的学生对象(自我解释),我的StudentsCollection()实例化存储我的学生对象的学生类型列表,当我尝试保存/加载我使用此代码的对象时,抛出以下异常:
/**
* Open student collection
*/
public void openCollection(){
try {
FileInputStream e = new FileInputStream("students.ser");
ObjectInputStream inputSteam = new ObjectInputStream(e);
while(inputSteam.readObject() != null){
this.list.add((Students)inputSteam.readObject());
}
} catch (FileNotFoundException var3) {
var3.printStackTrace();
JOptionPane.showMessageDialog(null, "File not found");
} catch (IOException var4) {
var4.printStackTrace();
JOptionPane.showMessageDialog(null, "IO Exception");
} catch (ClassNotFoundException var5) {
var5.printStackTrace();
JOptionPane.showMessageDialog(null, "Required class not found");
}
}
投掷:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2598)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1318)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at jdatabase.objects.students.StudentsCollection.openCollection(StudentsCollection.java:558)
at jdatabase.main.MainController.main(MainController.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
我只有一个Student对象添加到我的列表中,在保存列表并重新打开它之后,我要求控制台打印出该列表,Student实际打印出来。但是,当我创建多个学生对象并每次将其ID增加1并添加它们时,控制台会按顺序打印它们然后重新打印(出于某些奇怪的原因)并最终跳过一些。
如果您需要更多代码,请询问。 saveCollection()现在正常工作
修改后的代码: / **
* Open student collection
*/
public void openCollection(){
try {
FileInputStream e = new FileInputStream("students.ser");
ObjectInputStream inputSteam = new ObjectInputStream(e);
while((obj = inputSteam.readObject()) != null){
this.list.add((Students)obj);
}
} catch (FileNotFoundException var3) {
var3.printStackTrace();
JOptionPane.showMessageDialog(null, "File not found");
} catch (IOException var4) {
var4.printStackTrace();
JOptionPane.showMessageDialog(null, "IO Exception");
} catch (ClassNotFoundException var5) {
var5.printStackTrace();
JOptionPane.showMessageDialog(null, "Required class not found");
}
}
抛出:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2598)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1318)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at jdatabase.objects.students.StudentsCollection.openCollection(StudentsCollection.java:559)
at jdatabase.main.MainController.main(MainController.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
只有一个学生对象,并在控制台中打印以下内容:
学生姓名:学生 学生姓:默认 学生证:0学生 DoB:1/1/90
再次打印:
学生姓名:学生 学生姓:默认 学生证:0 学生DoB:1/1/90
答案 0 :(得分:2)
photoSettings.flashMode = .auto
在流的末尾不返回readObject()
,因此在循环终止条件下测试它是无效的。您的代码正确在遇到流结束时抛出null
。这里没有问题需要解决。
答案 1 :(得分:0)
您没有关闭输入流。我的猜测是你没有关闭输出流,而是它被截断了。使用“try-with-resource”。
try {
FileOutputStream e = new FileOutputStream("students.ser");
ObjectOutputStream outputStream = new ObjectOutputStream(e);
变为
try (
FileOutputStream e = new FileOutputStream("students.ser")
ObjectOutputStream outputStream = new ObjectOutputStream(e);
) {
(编辑到flush
包装器流(您不必一直走到并关闭它,但它可能是最好的,而不是冒一个常见的编程错误的风险)。)
那或你没有写下终止null
。
答案 2 :(得分:0)
问题是你的读取循环不知道要读取多少对象,所以它在文件末尾运行并获得EOFException
。
阅读代码执行此操作:
while (inputStream.readObject() != null) ...
问题是 (根据EJP的每条评论更新。)问题在于{ {1}} not 在达到EOF时返回null;如果首先将null写入流,它只返回null。因此,您无法检查null以检测EOF。为了避免这个问题,读取代码必须事先知道要读取多少个对象,必须以某种方式在序列化流中发送对象的数量,或者需要写入一个sentinel对象(或null)来指示读取应该停止。readObject
从不返回null。
从查看other question开始,编写代码如下所示:
readObject
据推测,// open objectOutputStream on a file
for (Student s : this.list) {
objectOutputStream.writeObject(s);
}
是list
或类似的。因此可以修改编写代码:
List<Student>
然后将阅读代码更改为:
objectOutputStream.writeObject(list.size());
for (Student s : this.list) {
objectOutputStream.writeObject(s);
}
这可能是不必要的,因为标准集合(例如int count = (int)objectInputStream.readObject();
for (int i = 0; i < count; i++) {
this.list.add((Student)objectInputStream.readObject());
}
)本身是可序列化的,前提是它们的内容是可序列化的。由于列表“知道”它包含多少元素,因此您不必编写计数,只需序列化和反序列化整个列表:
ArrayList
请注意,在反序列化时必须禁止未经检查的警告,因为实际上没有任何内容可以检查反序列化列表实际上是否包含objectOutputStream.writeObject(list);
...
@SuppressWarnings("unchecked")
List<Student> list = (List<Student>)objectInputStream.readObject();
个实例。