Search this site
|
What do you think of this article? Did it help you? Found a mistake? Feedback and suggestions here
StreamCorruptedException
A Java StreamCorruptedException can be thrown while deserialising data.
It essentially occurs in one of two main cases:
- you try to open an ObjectInputStream around some data that wasn't actually
written using an ObjectOutputStream;
- during a readObject() operation, the stream gets in the "wrong place".
Essentially, what happens is that, somehow or other, the writing and the
reading get "out of kilter". Here are a couple of ways it can happen:
- Forgetting to close the ObjectOutputStream that wrote the data (or closing the wrong stream)
If I had a dollar for every time I'd seen this mistake, I'd be typing this
article on a more expensive laptop. The mistake usually looks something like this:
OutputStream out = new FileOutputStream(f);
BufferedOutputStream bout = new BufferedOutputStream(out);
ObjectOutputStream oout = new ObjectOutputStream(bout);
oout.write(object);
out.close();
The problem here is that we've closed the wrong stream. In between the actual
FileOutputStream and the object writing, there is a layer of buffering.
Thus, when we close the underlying output stream, there is a risk that some of
the data is still "stuck" in the buffer.
The solution is simple, and is how you should always handle closing
streams: ALWAYS close the stream that was created last, in this
case, the ObjectOutputStream. This way, each layer of streaming has
a chance to pass any buffered data down to the stream below it (and by definition,
the close() method must do so). Note that you don't need
to close every stream— just the outer one.
- Forgetting to check the return value of InputStream.read().
This is also a mistake I've seen time and time again.
It happens when you're manually chopping up an input stream
into sections and then passing part of the stream to an ObjectInputStream.
Each section might be preceded by a four-byte length marker, for example:
public Object readObject(InputStream in) throws IOException, ... {
int objDataLen = readInt(in);
byte[] objData = new byte[objDataLen];
in.read(objData);
ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(objData));
return oin.readObject();
}
Here, our capital sin is that we assume that the read() method
will fill the array. It won't necessarily, and we end up with a partial
object stream. The problem can be especially difficult to track down when the bytes are
coming in over a network, because the problem will be intermittent and essentially
random.
If this problem occurs at some point in the stream, then it will
have a knock-on effect on later parts of the stream. The solution is to
be careful to always check the return value of InputStream.read()
when reading into an array.
Written by Neil Coffey. Copyright © Javamex UK 2009. All rights reserved.
|