How to read DataInputStream until the end without needing to catch an EOFException?

≡放荡痞女 提交于 2019-12-13 22:09:21

问题


Suppose we have some binary data byte[] data that only contains Integers. If I wanted to read this data utilizing a DataInputStream, the only approach I can come up with is the following:

DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
try {
    while (true){
        int i = in.readInt();
    }
} catch (EOFException e) {
    // we're done!
} catch (IOException e){
    throw new RuntimeException(e);
}

What bugs me about this is that reaching the end of the stream is expected and it would exceptional only if no exception was thrown, what IMO defeats the purpose of exceptions in the first place.

When using Java NIO's IntBuffer, there's no such problem.

IntBuffer in = ByteBuffer.wrap(data).asIntBuffer();
while (in.hasRemaining()){
    int i = in.get();
}

Coming from C# and being in the process of learning Java I refuse to believe that this is the intended way of doing this.

Moreover, I just came across Java NIO which seems to be "quite new". Using IntBuffer here instead would be my way of procrastinating the matter. Regardless, I wanna know how this is properly done in Java.


回答1:


You can't. readInt() can return any integer value, so an out-of-band mechanism is required to signal end of stream, so an exception is thrown. That's how the API was designed. Nothing you can do about it.




回答2:


Since you are coming from .NET, Java's DataInputStream is roughly equivalent to BinaryReader of .NET.

Just like its .NET equivalent, DataInputStream class and its main interface, DataInput, have no provision for determining if a primitive of any given type is available for retrieval at the current position of the stream.

You can gain valuable insight of how the designers of the API expect you to use it by looking at designer's own usage of the API.

For example, look at ObjectInputStream.java source, which is used for object deserialization. The code that reads arrays of various types calls type-specific readXYZ methods of DataInput in a loop. In order to figure out where the primitives end, the code retrieves the number of items (line 1642):

private Object readArray(boolean unshared) throws IOException {
    if (bin.readByte() != TC_ARRAY) {
        throw new InternalError();
    }
    ObjectStreamClass desc = readClassDesc(false);
    int len = bin.readInt();
    ...
    if (ccl == Integer.TYPE) {
        bin.readInts((int[]) array, 0, len);
        ...
    }
    ...
}

Above, bin is a BlockDataInputStream, which is another implementation of DataInput interface. Note how len, the number of items in the array stored by array serialization counterpart, is passed to readInts, which calls readInt in a loop len times (line 2918).



来源:https://stackoverflow.com/questions/47642501/how-to-read-datainputstream-until-the-end-without-needing-to-catch-an-eofexcepti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!