Java ObjectInputStream 无效的流标头:00000000

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21635198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:47:22  来源:igfitidea点击:

ObjectInputStream Invalid Stream Header: 00000000

java

提问by karoma

I want to use a single ObjectInputStream to read from a byte array, but I keep getting a StreamCorruptedException every time I start the program.

我想使用单个 ObjectInputStream 从字节数组中读取,但每次启动程序时我都会收到 StreamCorruptedException。

public void run(){

        byte[] receiveBuffer = new byte[65535];

        bIn = new ByteArrayInputStream(receiveBuffer);

        try {
            in = new ObjectInputStream(bIn);
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        while(true){
            try {
                packetIn = new DatagramPacket(receiveBuffer, receiveBuffer.length);
                sock.receive(packetIn);

                Object o = in.readObject();
                //do things with o
            }
        }
}

I'm just trying to initialize the ObjectInputStream to read from the byte array eventually, but it's throwing that exception even if I remove the while loop.

我只是试图初始化 ObjectInputStream 以最终从字节数组中读取,但即使我删除了 while 循环,它也会抛出该异常。

What am I doing wrong here?

我在这里做错了什么?

采纳答案by yshavit

If you take a look at the javadocs for the ObjectInputStream(InputStream)constructor, you'll see:

如果您查看ObjectInputStream(InputStream)构造函数的 javadoc ,您会看到:

Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the streamand verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.

...

throws

    StreamCorruptedException- if the stream header is incorrect

创建一个从指定的 InputStream 读取的 ObjectInputStream。从流中读取并验证序列化流标头。此构造函数将阻塞,直到相应的 ObjectOutputStream 已写入并刷新标头。

...

投掷

    StreamCorruptedException- 如果流标头不正确

(emphasis added)

(强调)

In other words, the constructor doesn't just record the InputStreamreference you give it, it also reads from that object. In this case, that's a stream of all 0s.

换句话说,构造函数不只是记录InputStream你给它的引用,它还从那个对象中读取。在这种情况下,这是所有0s的流。

You should defer creating the ObjectInputStreamuntil you have the serialized data (or at least enough of it to read the header).

您应该推迟创建,ObjectInputStream直到您拥有序列化数据(或至少有足够的数据来读取标头)。

(In the interest of "teach a person to fish," I'll also note that any time a method/constructor throws an exception you don't expect, that method's javadocs are a good place to start for understanding its behavior. The javadocs for the JDK classes are usually pretty good.)

(为了“教人钓鱼”,我还要指出,任何时候方法/构造函数抛出您不希望的异常时,该方法的 javadoc 都是了解其行为的好起点。javadoc对于 JDK 类通常非常好。)

回答by Joni

The stream protocol includes a stream header, which ObjectInputStreamreads in the constructor. You have to defer creating the stream until you have received something:

流协议包括一个流头,它ObjectInputStream在构造函数中读取。你必须推迟创建流,直到你收到一些东西:

    sock.receive(packetIn);

    try {
        in = new ObjectInputStream(bIn);
        Object o = in.readObject();
    } catch (IOException e1) {
        e1.printStackTrace();
    }

回答by Hans Verschoor

Ok, this is how object streams work and the solution that works everywhere.

好的,这就是对象流的工作方式以及适用于任何地方的解决方案。

Object stream data is preceded by a 4 byte 'magical' sequence AC ED 00 05. An ObjectInputStream will peek for this data at construction time rather than before the first read. And that's logical: one wants to be sure it is a proper stream before being too far in an application. The sequence is buffered by the ObjectOutputStream at construction time so that it is pushed on the stream at the first write. This method often leads to complexities in buffered situations or transferring via pipes or sockets. Fortunately, there is a just as simple as an effective solution to all these problems:

对象流数据前面有一个 4 字节的“神奇”序列 AC ED 00 05。ObjectInputStream 将在构建时而不是在第一次读取之前查看此数据。这是合乎逻辑的:在应用程序中太远之前,人们希望确保它是一个正确的流。该序列在构造时由 ObjectOutputStream 缓冲,以便在第一次写入时将其推送到流上。这种方法通常会导致缓冲情况或通过管道或套接字传输的复杂性。幸运的是,对于所有这些问题,有一个与有效解决方案一样简单的方法:

Flush the ObjectOutputStream immediately after construction!

构造后立即刷新 ObjectOutputStream!

ObjectOutputStream myStream = new ObjectOutputStream ( anotherStream );
myStream.flush();

In your case, you will have to use a ObjectOutputStreamif you want to read from an ObjectInputStream

在您的情况下,如果您想从 ObjectInputStream 读取,则必须使用ObjectOutputStream