web-dev-qa-db-ja.com

EOFException-処理方法

私は初心者ですJava Javaチュートリアル に従うプログラマー。

私はシンプルなJava JavaチュートリアルData Streamsページ からのプログラムを使用していますが、実行時に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チュートリアルデータストリームページ から、

DataStreamsは、無効な戻り値をテストする代わりに、 EOFException をキャッチすることでファイルの終わり状態を検出することに注意してください。 DataInputメソッドのすべての実装は、戻り値の代わりにEOFExceptionを使用します。

だから、これはEOFExceptionをキャッチするのが正常であるということを意味するので、それをキャッチして処理しないだけで問題ありません。つまり、ファイルの終わりに達しますか?

それを処理する必要がある場合は、その方法を教えてください。

[〜#〜] edit [〜#〜]

提案から、whileループ条件にin.available() > 0を使用して修正しました。

または、例外を処理するために何もできませんでした。

20
Jonathan Lam

ファイルからの読み取り中は、ループを終了していません。そのため、すべての値を読み取り、正しくは次の行の読み取りの次の反復でEOFExceptionをスローします。

 price = in.readDouble();

ドキュメントを読むと、次のように表示されます。

スロー:

EOFException-この入力ストリームが8バイトを読み込む前に終わりに達した場合。

IOException-ストリームは閉じられており、含まれている入力ストリームは閉じた後の読み取りをサポートしていないか、別のI/Oエラーが発生します。

問題を解決するために、whileループに適切な終了条件を設定します。以下:

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

これを処理する最善の方法は、適切な条件で無限ループを終了することです。

ただし、例外処理を要求したため:

2つのキャッチを使用してみてください。 EOFExceptionは予期されているため、発生しても問題はないようです。その他の例外は処理する必要があります。

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

または、次を使用して、最初に要素の数を(ヘッダーとして)書き出すこともできます。

out.writeInt(prices.length);

ファイルを読み取るとき、最初にヘッダー(要素数)を読み取ります。

int elementCount = in.readInt();

for (int i = 0; i < elementCount; i++) {
     // read elements
}
2
Katona

while(in.available() != 0)の代わりにwhile(true)を使用できます。

2
akaHuman

EOFException(ファイルの終わり)をチェックするのではなく、InputStreamから読み取り、スニペットwhile(in.available()>0)を使用してストリームの終わりをチェックするコードに出くわすことがあります。

この手法の問題、およびJavadocはこれをエコーし​​ますが、次の呼び出し元をブロックせずに読み取ることができるブロックの数のみを通知するということです。つまり、読み取るバイト数がさらにある場合でも、_return 0_を使用できます。したがって、InputStream available()メソッドを使用して、ストリームの終わりを確認しないでください。

while (true)を使用する必要があります

_catch(EOFException e) {
//This isn't problem
} catch (Other e) {
//This is problem
}
_
1
Taleh Alqayev

IOExceptionをキャッチしますが、EOFExceptionも継承されます。 tutorial の例を見ると、EOFExceptionをキャッチする必要があることを強調しています-これが彼らのすることです。問題を解決するには、EOFExceptionの前にIOExceptionをキャッチします。

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

例外を除いて、例外を使用したデータフロー制御は好きではありません。これは例外の使用目的ではないため、(私の意見では)本当に悪いスタイルです。

0
Jost

Try catchブロック内にコードを配置します:すなわち:

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