感谢大家的大力帮助,在这里我必须为这个例外添加一个可能的原因:
如果您在域类中添加readObject()
和writeObject()
(如下面的类大学),并且您还必须在main()方法中调用ObjectOutputStream.writeObject()
方法,请确保:< / p>
---不要在域类中放置ObjectOutputStream.close()
方法。它会导致异常,因为对它进行操作是非法的,因为它已关闭(程序如何在文件已经关闭后读取文件或关闭文件?)。
我知道这是一个小问题,但调试非常微妙,因为异常不会告诉它任何事情。所以这是一个有点想要记录。
我尝试实现一个简单的片段来破坏瞬态对象的序列化,它将序列化该瞬态对象的原始字段,然后通过ObjectInputStream对这些原始字段进行反序列化,最后用它们组成一个新对象。场景是这样的:
public class College implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private transient City city; //transient
private String zipCode;
// constructors & getter/setters
private void writeObject(ObjectOutputStream os){
try {
os.defaultWriteObject();
os.writeInt(city.getCode());
os.writeInt(city.getPopulation());
os.writeObject(city.getName());
os.flush();
os.close(); // update: not good practice, may throw exception.
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void readObject(ObjectInputStream os){
try {
os.defaultReadObject();
int code = os.readInt();
int population = os.readInt();
String name = (String)os.readObject();
City theCity = new City(code, name, population);
System.out.println(theCity.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这是City类
public class City {
// the primitive & String fields
private int code;
private String name;
private int population;
// getter/setters
}
这是编写和阅读college
对象的可爱代码(有点粗略,对不起)
public class GeneralTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
City city = new City(375, "New York", 380897);
College college = new College("NYU", city, "10289");
College readCollege = null;
City readCity = null;
System.out.println("Before serialization -- City: ["+city.toString()+"], College: ["+college.toString()+"]");
try {
FileOutputStream fs = new FileOutputStream("college.foo");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(college);
os.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
FileInputStream fis = new FileInputStream("college.foo");
ObjectInputStream ois = new ObjectInputStream(fis);
readCollege = (College)ois.readObject();
//get values to compose a city object
int id = ois.readInt();
int population = ois.readInt();
String name = ois.readUTF();
readCity = new City(id, name, population);
ois.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("After serialization -- City: ["+readCity.toString()+"], College: ["+readCollege.toString()+"]");
}
}
然后我得到了这个例外,而readCollege
和readCity
显然是空的:(
java.io.IOException: Write error
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:282)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1847)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1756)
at java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1257)
at java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1211)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1395)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeFatalException(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:333)
at serialized.GeneralTest.main(GeneralTest.java:27)
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.readByte(ObjectInputStream.java:2721)
at java.io.ObjectInputStream$BlockDataInputStream.readUTFChar(ObjectInputStream.java:3113)
at java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3010)
at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2819)
at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1050)
at serialized.College.readObject(College.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:969)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at serialized.GeneralTest.main(GeneralTest.java:40)
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2553)
at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1899)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1873)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at serialized.GeneralTest.main(GeneralTest.java:40)
Exception in thread "main" java.lang.NullPointerException
at serialized.GeneralTest.main(GeneralTest.java:52)
有什么想法吗?提前谢谢。
答案 0 :(得分:1)
以下是您输出的代码部分
FileOutputStream fs = new FileOutputStream("college.foo");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(college);
os.close();
您创建了自己的流,编写了college
对象,然后关闭它。
这是你正在阅读的部分:
FileInputStream fis = new FileInputStream("college.foo");
ObjectInputStream ois = new ObjectInputStream(fis);
readCollege = (College)ois.readObject();
此时,您已经阅读了所写的所有内容。你之前写过大学,现在你读了它。
然后你去做:
//get values to compose a city object
int id = ois.readInt();
int population = ois.readInt();
String name = ois.readUTF();
readCity = new City(id, name, population);
你怎么能在这里读书?你只写了college
。然后你读回college
(进入readCollege
引用。然后你试图读取另外两个整数和一个字符串?那些数据应该来自哪里?没有什么可读的。< / p>
答案 1 :(得分:1)
用ois.readObject()替换ois.readUTF()并将其强制转换为String。
String name = (String) ois.readObject();
没有编译/尝试过......
答案 2 :(得分:1)
执行此行时:
readCollege = (College)ois.readObject();
之后流中没有任何东西了。
所以你的未来尝试阅读相同的流会抛出逻辑java.io.EOFException
:
(此外,请注意readUTF()
替换readObject()
)
//get values to compose a city object
int id = ois.readInt(); // there's nothing more !! throws exception!
int zip = ois.readInt();
String name = (String)ois.readObject();
实际上,在写入流时,您尚未添加自定义值。
所以,一个解决方案示例,添加三行专用于添加City
所需的元素:
try {
FileOutputStream fs = new FileOutputStream("college.foo");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(college);
os.writeInt(1); //adding the id !
os.writeInt(75019); //adding the zip !
os.writeObject("name"); //adding the name !
os.close();
} catch (IOException e) {
e.printStackTrace();
}
当然,阅读字段的顺序必须是写作期间的相同。
在您的评论后更新:
事实上,您已经通过City
方法在College
课程中阅读了readObject()
的自定义值,因此这些行无用:
int id = ois.readInt();
int population = ois.readInt();
String name = (String)ois.readObject(); // remove them all
为什么???因为他们只是抛出java.io.EOFException
,因为我之前解释过没有其他内容可读。
这是一个有效的全球代码:
class College implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private transient City city; //transient
private String zipCode;
College(String name, City city, String zipCode) {
this.name = name;
this.city = city;
this.zipCode = zipCode;
}
private void readObject(ObjectInputStream os) {
try {
os.defaultReadObject();
int code = os.readInt();
int population = os.readInt();
String name = (String) os.readObject();
this.city = new City(code, name, population);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void writeObject(ObjectOutputStream os) {
try {
os.defaultWriteObject();
os.writeInt(1);
os.writeInt(200);
os.writeObject("thename");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
}
class City {
// the primitive & String fields
private int code;
private String name;
private int population;
City(int code, String name, int population) {
this.code = code;
this.name = name;
this.population = population;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
// getter/setters
}
public class Launcher {
public static void main(String[] args) {
// TODO Auto-generated method stub
City city = new City(375, "New York", 380897);
College college = new College("NYU", city, "10289");
College readCollege = null;
City readCity = null;
System.out.println("Before serialization -- City: [" + city.toString() + "], College: [" + college.toString() + "]");
try {
FileOutputStream fs = new FileOutputStream("college.foo");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(college);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fis = new FileInputStream("college.foo");
ObjectInputStream ois = new ObjectInputStream(fis);
readCollege = (College) ois.readObject();
readCity = readCollege.getCity();
ois.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("After serialization -- City: [" + readCity.toString() + "], College: [" + readCollege.toString() + "]");
}
}