【问题标题】:EOFException - how to handle?EOFException - 如何处理?
【发布时间】:2013-08-29 08:41:31
【问题描述】:

我是一名初学者,关注java tutorials

我正在使用来自Java tutorialsData Streams Page 的简单Java 程序,并且在运行时,它一直显示EOFException。我想知道这是否正常,因为读者最终必须到达文件的末尾。

import java.io.*;

public class DataStreams {
    static final String dataFile = "F://Java//DataStreams//invoicedata.txt";

    static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };
    static final int[] units = { 12, 8, 13, 29, 50 };
    static final String[] descs = {
        "Java T-shirt",
        "Java Mug",
        "Duke Juggling Dolls",
        "Java Pin",
        "Java Key Chain"
    };
    public static void main(String args[]) {
        try {
            DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile)));

            for (int i = 0; i < prices.length; i ++) {
                out.writeDouble(prices[i]);
                out.writeInt(units[i]);
                out.writeUTF(descs[i]);
            }

            out.close(); 

        } catch(IOException e){
            e.printStackTrace(); // used to be System.err.println();
        }

        double price;
        int unit;
        String desc;
        double total = 0.0;

        try {
            DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFile)));

            while (true) {
                price = in.readDouble();
                unit = in.readInt();
                desc = in.readUTF();
                System.out.format("You ordered %d" + " units of %s at $%.2f%n",
                unit, desc, price);
                total += unit * price;
            }
        } catch(IOException e) {
            e.printStackTrace(); 
        }

        System.out.format("Your total is %f.%n" , total);
    }
}

它编译得很好,但输出是:

You ordered 12 units of Java T-shirt at $19.99
You ordered 8 units of Java Mug at $9.99
You ordered 13 units of Duke Juggling Dolls at $15.99
You ordered 29 units of Java Pin at $3.99
You ordered 50 units of Java Key Chain at $4.99
java.io.EOFException
        at java.io.DataInputStream.readFully(Unknown Source)
        at java.io.DataInputStream.readLong(Unknown Source)
        at java.io.DataInputStream.readDouble(Unknown Source)
        at DataStreams.main(DataStreams.java:39)
Your total is 892.880000.

来自Java tutorialsData Streams Page,它说:

请注意,DataStreams 通过捕获 EOFException 来检测文件结束条件,而不是测试无效的返回值。 DataInput 方法的所有实现都使用 EOFException 而不是返回值。

那么,这是否意味着捕获EOFException是正常的,所以只捕获它而不处理它就可以了,意味着到达文件末尾?

如果这意味着我应该处理它,请告诉我如何处理。

编辑

根据建议,我已通过将 in.available() &gt; 0 用于 while 循环条件来修复它。

或者,我无法处理异常,因为它很好。

【问题讨论】:

  • 删除e.printStackTrace(); 块中的e.printStackTrace(); 将删除异常堆栈跟踪的打印。而不是打印它,你应该记录它。

标签: java exception try-catch


【解决方案1】:

EOFException 是 IOException 的子级 我更喜欢下面的 ==>

try {
        .
        .
        .
    } catch (IOException e) {
        if (!(e instanceof EOFException)) {
            throw new RuntimeException(e);
        }
    }

【讨论】:

    【解决方案2】:

    您可能会遇到从 InputStream 读取并使用 sn-p 的代码 while(in.available()&gt;0) 检查流的结尾,而不是检查 EOFException(文件结尾)。

    这种技术的问题,Javadoc 确实回应了这一点,它只告诉你在不阻塞下一个调用者的情况下可以读取的块数。换句话说,即使有更多字节要读取,它也可以return 0。因此,永远不要使用InputStream available() 方法来检查流的结尾。

    您必须使用while (true)

    catch(EOFException e) {
    //This isn't problem
    } catch (Other e) {
    //This is problem
    }
    

    【讨论】:

      【解决方案3】:

      从文件中读取时,您并没有终止循环。因此,它读取了所有值并正确在下一次读取迭代中抛出 EOFException 如下行:

       price = in.readDouble();
      

      如果您阅读文档,它会说:

      投掷:

      EOFException - 如果此输入流在读取八个字节之前到达末尾。

      IOException - 流已关闭且包含的输入流不支持关闭后读取,或发生另一个 I/O 错误。

      在您的 while 循环中放置适当的终止条件以解决问题,例如下面:

           while(in.available() > 0)  <--- if there are still bytes to read
      

      【讨论】:

      • 当没有更多数据当前可供读取, 并且不是 就在流的末尾时,此循环将退出。 InputStream.available() 不是流结束的测试。请参阅 Javadoc。
      【解决方案4】:

      将您的代码放入 try catch 块中: 即:

      try{
        if(in.available()!=0){
          // ------
        }
      }catch(EOFException eof){
        //
      }catch(Exception e){
        //
      }
      }
      

      【讨论】:

        【解决方案5】:

        处理此问题的最佳方法是在适当的条件下终止无限循环。

        但是既然你要求异常处理:

        尝试使用两个catch。您的 EOFException 是预期的,因此发生时似乎没有问题。应处理任何其他异常。

        ...
        } catch (EOFException e) {
           // ... this is fine
        } catch(IOException e) {
            // handle exception which is not expected
            e.printStackTrace(); 
        }
        

        【讨论】:

        • 这就是他们在Data Streams 示例中所做的。它也有效。
        【解决方案6】:

        或者,您可以先写出元素的数量(作为标题),使用:

        out.writeInt(prices.length);
        

        读取文件时,首先读取文件头(元素计数):

        int elementCount = in.readInt();
        
        for (int i = 0; i < elementCount; i++) {
             // read elements
        }
        

        【讨论】:

        • 是的,我可以使用它,但它比@yogendra singh 的建议更不方便
        • @Jon 是的,它也不安全(文件可能为空等),只是显示为替代
        【解决方案7】:

        你捕获了IOException,它也捕获了EOFException,因为它是继承的。如果您查看tutorial 中的示例,他们强调您应该抓住EOFException - 这就是他们所做的。为了解决你的问题,在IOException之前捕获EOFException

        try
        {
            //...
        }
        catch(EOFException e) {
            //eof - no error in this case
        }
        catch(IOException e) {
            //something went wrong
            e.printStackTrace(); 
        }
        

        除此之外,我不喜欢使用异常进行数据流控制 - 这不是异常的预期用途,因此(在我看来)这种风格非常糟糕。

        【讨论】:

        • 正是他的例外的“预期用途”。您的“原则”的问题在于例外*是一种流控制形式。
        【解决方案8】:

        您可以使用while(in.available() != 0) 代替while(true)

        【讨论】:

        • hasNextLine() 不是 DataInputStream 的一部分。这个答案是错误的。
        • 对不起!我没看到。我现在改了。
        • 这个答案还是错的。 InputStream.available() 不是流结束的测试。请参阅 Javadoc。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-04
        • 1970-01-01
        • 1970-01-01
        • 2013-03-02
        • 2013-10-16
        相关资源
        最近更新 更多