【问题标题】:StreamCorruptedException: invalid stream headerStreamCorruptedException:无效的流标头
【发布时间】:2015-11-30 16:43:23
【问题描述】:

我有一个类序列化器

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);

我是这样读的

int length = in.readInt();
            if (length > 0) {
                byte[] bytes = new byte[length];
                in.readFully(bytes);
                byte[] result = sp.processInput(bytes);
            }

然后当我尝试反序列化我的 Person 对象(可序列化)时,它会抛出一个错误

Person person = (Person) Serializer.deserialize(bytes);
java.io.StreamCorruptedException: invalid stream header: 03ACED00
at model.Serializer.deserialize(Serializer.java:22)

人物类:

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;

我不能使用普通的图像,因为它不可序列化,所以我想出了这个类。

SerializableImage 类

public class SerializableImage implements Serializable {
private int width, height;
private int[][] data;

public SerializableImage(Image image) {
    setImage(image);
}

public void setImage(Image image){...}
public Image getImage() {...}

我一开始就不能使用 ObjectInputStream,因为我的字节数组包含第一个字节,说明如何处理所需的对象。

当我发送字符串和其他核心对象时,一切正常。

你能指出我哪里出错了吗?

【问题讨论】:

  • 请展示一个简短但完整的程序,我们可以使用它来重现该问题。提示:问题很可能出在要么在序列化中在传输中。您应该分别测试每个以找出它是什么,然后只在问题中包含相关的一个。

标签: java sockets serialization client


【解决方案1】:
java.io.StreamCorruptedException: invalid stream header: 03ACED00

正确的流标头应该是ACED00..。很明显,您有先前反序列化留下的03 字节。所以你的(未公开的)字节数组读取代码中有一个错误,顺便说一句,它应该看起来像这样:

int len = din.readInt();
byte[] data = new byte[len];
din.readFully(data);

等等

但是这里根本没有理由使用ByteArrayInput/OutputStreamDataInput/OutputSream。只需使用

new ObjectOutputStream(socket.getOutputStream())

new ObjectInputStream(socket.getInputStream())

这些在每个套接字的生命周期内分配一次,并直接使用writeObject()readObject()。你这样做的方式没有任何优势,只有这样的错误机会。

我一开始就不能使用 ObjectInputStream,因为我的字节数组包含第一个字节,说明如何处理所需的对象。

这是不正确的。只需使用标记字节调用write(),然后调用writeObject()。在对端,调用read()获取标签字节,然后调用readobject()

显然您在将第一个字节提供给new ObjectInputStream(...) 之前未能删除它。

【讨论】:

  • "正确的流标头应该是 ACED00...所以很明显,您有前一次反序列化留下的 03 字节。"我很好奇你是怎么知道这个的?正确的标题不会以 03 开头(这也是有效的十六进制)是否有原因?
猜你喜欢
  • 1970-01-01
  • 2012-08-06
  • 2013-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
  • 2011-02-25
  • 1970-01-01
相关资源
最近更新 更多