Java的EOFException是特殊的吗?

时间:2010-07-27 15:59:47

标签: java exception io inputstream eofexception

使用异常表示已到达文件末尾似乎很脏。我们阅读的每个文件都有一个结尾,所以它似乎并不特殊或意外。此外,我不喜欢对我的程序的非异常流程使用异常。

我说的是使用java.io.EOFException来表示数据输入流的结束:

想象一个包含以下消息的文件......

----------------- ------------------
- 2-byte LENGTH - - N-byte PAYLOAD - , where N = LENGTH;
----------------- ------------------

...并使用DataInputStream读取此文件:

DataInputStream in = new DataInputStream(...);

...

try {
    while (true) {
        short length = in.readShort();
        byte[] b = new byte[length];
        in.readFully(b);
    }
} catch (EOFException e) { }

...

在此示例中,调用in.readShort()会引发EOFException。我应该计算出文件中的字节数,并准确读取该字节数(由total -= length确定为零),并退出while循环而没有异常?我正在寻找最佳实践。

我应该这样做吗?

long total = file.length();
while (total > 0) {
    short length = in.readShort();
    total -= length;
    byte[] b = new byte[length];
    in.readFully(b);
}

API规范指定在输入期间EOFException表示文件的结尾或流的结尾意外。但是它也被数据输入流用来表示流的结束。

预计例外时我该怎么办?

3 个答案:

答案 0 :(得分:2)

有关DataInput.readFully方法的信息,请参阅API specification

 This method blocks until one of the following conditions occurs:

    * b.length bytes of input data are available, in which case a normal return is made.
    * End of file is detected, in which case an EOFException is thrown.
    * An I/O error occurs, in which case an IOException other than EOFException is thrown.

所以这个想法是它要么读取b.length个字节的数据,要么因为I / O错误或者在b.length个字节之前达到文件结尾而得到错误。请阅读。

因此,在调用DataInput.readFully之前,您需要知道要读取的字节数。如果你超过了文件的末尾,那就被认为是异常行为,因此,这就是你获得异常的原因。

答案 1 :(得分:1)

您提到了通常给出的建议,即异常应仅用于发出异常事件的信号。这个建议的问题在于它取代了一个不确定性("何时抛出异常')与另一个("什么是例外")。

另一个更好的答案是,当且仅当替代方案未能建立后置条件或维持不变量时,您应该抛出异常。

对输入流的读取操作的后置条件是已成功读取值。显然,如果我们在EOF,就无法读取任何价值。因此必须抛出某种类型的异常。调用代码希望暂停读取,因此它必须是一种独特的异常类型(不是一般的IOException)。因此,特定的EOFException是必要的。

另一种方法是读取操作没有成功读取作为后置条件。这就是C(POSIX)API的功能。实际上,每次读取操作实际上都是一种尝试读取操作。然后,读者代码需要检查状态代码以查看读取的尝试是否实际成功。这种代码风格难以理解,冗长且容易出错。使用例外而不是状态代码的动机之一就是避免这些困难。

答案 2 :(得分:0)

顾名思义,当您希望完全读取已知长度的一些字节时,会使用readFully。如果之前达到EOF,那是意料之外的,那么从概念上讲它是正确的抛出异常。如果您需要read语义,请使用read方法。