如何在不需要捕获 EOFException 的情况下读取 DataInputStream 直到结束?

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

假设我们有一些只包含整数的二进制数据byte[] data。如果我想使用 DataInputStream 读取此数据,我唯一能想到的方法如下:

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

让我感到困扰的是,到达流的末尾是预期的,只有在没有抛出异常的情况下才会异常,IMO破坏了异常的目的第一名.

使用JavaNIO的IntBuffer时,没有这个问题

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

来自 C# 并且正在学习 Java 我拒绝相信这是这样做的预期方式。

另外,我刚刚遇到了Java NIO,好像是"quite new"。在这里使用 IntBuffer 将是我拖延此事的方式。无论如何,我想知道如何在 Java.

中正确完成此操作

你不能。 readInt() 可以 return 任何整数值,因此需要带外机制来指示流结束,因此会抛出异常。 API 就是这样设计的。你对此无能为力。

由于您来自 .NET,Java 的 DataInputStream is roughly equivalent to BinaryReader of .NET。

就像它的 .NET 等效项一样,DataInputStream class 及其主界面 DataInput 没有规定确定任何给定类型的基元是否可用于检索流的当前位置。

通过查看设计者自己对 API 的使用,您可以获得有关 API 的设计者希望您如何使用它的宝贵见解。

例如,查看ObjectInputStream.java源,它用于对象反序列化。读取各种类型数组的代码在循环中调用 DataInput 的特定于类型的 readXYZ 方法。为了弄清楚基元在哪里结束,代码检索了项目的数量(第 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);
        ...
    }
    ...
}

上面,bin是一个BlockDataInputStream,是DataInput接口的另一种实现。请注意 len,数组序列化对应项存储的数组中的项数,如何传递给 readInts,后者在循环中调用 readInt len 次(第 2918 行) .