StreamCorruptedException:无效的流标头

时间:2015-11-30 16:43:24

标签: java sockets serialization client

我有一个类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,因为我的字节数组包含第一个字节,说明如何处理欲望化的对象。

当我发送字符串和其他核心对象时,一切都很好。

请指出我有错误的地方?

1 个答案:

答案 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/OutputStreamDataInput/OutputSream。只需使用

new ObjectOutputStream(socket.getOutputStream())

new ObjectInputStream(socket.getInputStream())

这些在每个套接字的生命周期中分配一次,并直接使用writeObject()readObject()。你做这件事的方式没有任何好处,只有像这样的bug的机会。

  

我不能首先使用ObjectInputStream,因为我的字节数组包含第一个字节,说明如何处理欲望化的对象。

这不正确。只需使用标记字节调用write(),然后writeObject()。在对等方,调用read()以获取标记字节,然后readobject()

显然,在将第一个字节提供给new ObjectInputStream(...)之前,您无法将其删除。