我有一个类Serializer
ID
我的客户通过
发送数据public class Serializer {
private Serializer() {}
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(b);
out.writeObject(obj);
return b.toByteArray();
}
public static Object deserialize(byte [] bytes) throws IOException, ClassNotFoundException {
if (bytes == null) return null;
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream in = new ObjectInputStream(b);
return in.readObject();
}
}
我这样读了
private static DataInputStream in;
private static DataOutput out;
...
out.writeInt(bytes.length);
out.write(bytes);
然后当我尝试反序列化我的Person对象(可序列化)时,它会抛出错误
int length = in.readInt();
if (length > 0) {
byte[] bytes = new byte[length];
in.readFully(bytes);
byte[] result = sp.processInput(bytes);
}
人员类:
Person person = (Person) Serializer.deserialize(bytes);
java.io.StreamCorruptedException: invalid stream header: 03ACED00
at model.Serializer.deserialize(Serializer.java:22)
我不能使用普通图像,因为它不可序列化,所以我想出了这个类。
SerializableImage类
public class Person implements Serializable {
private String creationDate;
private String name;
private String birthDate;
private String city;
private String phoneNumber;
private String email;
private String university;
private String place;
private String reason;
private SerializableImage photo;
private boolean attended;
我不能首先使用ObjectInputStream,因为我的字节数组包含第一个字节,说明如何处理欲望化的对象。
当我发送字符串和其他核心对象时,一切都很好。
请指出我有错误的地方?
答案 0 :(得分:2)
java.io.StreamCorruptedException: invalid stream header: 03ACED00
正确的流标头为ACED00..
。很明显,你在之前的反序列化中遗留了03
个字节。所以你的(未公开的)字节数组读取代码中有一个错误,BTW应该是这样的:
int len = din.readInt();
byte[] data = new byte[len];
din.readFully(data);
等
HOWEVER 此处没有理由使用ByteArrayInput/OutputStream
或DataInput/OutputSream
。只需使用
new ObjectOutputStream(socket.getOutputStream())
和
new ObjectInputStream(socket.getInputStream())
这些在每个套接字的生命周期中分配一次,并直接使用writeObject()
和readObject()
。你做这件事的方式没有任何好处,只有像这样的bug的机会。
我不能首先使用ObjectInputStream,因为我的字节数组包含第一个字节,说明如何处理欲望化的对象。
这不正确。只需使用标记字节调用write()
,然后writeObject()
。在对等方,调用read()
以获取标记字节,然后readobject()
。
显然,在将第一个字节提供给new ObjectInputStream(...)
之前,您无法将其删除。