0

if / elseを介してファイルの存在を確認する方法を知っており、以前の割り当てで機能しました。

File f = new File("file.txt");
    if (f.exists() && f.canRead()) {
        // Code goes here.
    } else { } // Error message.

ただし、バッファリングされた画像で同じことを行うと、次のようになります。

private BufferedImage img;

File f = new File("pic.png");
    if (f.exists() && f.canRead()) {
        img = ImageIO.read(f);
    } else { } // Error message.

次に、コンパイラーは、目的を無効にするtry/catchまたは@throwsを要求します。私は何が間違っているのですか?すべてのスプライトを.jarにパッケージ化し、それらをリソースとして呼び出す方がよいでしょうか(終了したら実行する予定です)。

それが問題になる場合は、JRE 1.6で実行しており、ファイルチェックはswitchcaseステートメント内にあります。

4

4 に答える 4

2

チェックされた例外として、それをキャッチする必要があります。実際に投げられたかどうかは関係ありません。手動のエラー処理では、すべてのケースを処理できるわけではありません。ネットワークドライブから読み取りを行っていて、読み取り中に接続が中断される可能性があると考えてください。

上記のコメントを見て更新してください。言われたように、例外がスローされる可能性があり、仕様ごとに必要なチェックされた例外の処理が行われる可能性があるため、try/catchブロックを構築する必要があります。事前のチェックにより、すでにのリスクを回避していますFileNotFoundException。実装がエラーをまったくスローしないクラスを作成したこともありますが、それでもインターフェイスで処理する必要があります(例:ByteArryOutputStream.close())

于 2012-11-27T06:39:01.170 に答える
2

try / catchブロックを使用しても、目的がまったく損なわれることはありません。

ファイルが存在し、読み取り可能であっても、スローされる可能性のある例外は他にもたくさんあります。

考えられる例:

  • 読み取り中にファイルが削除されます
  • ファイルの読み取り中に、ファイルへのアクセス許可が取り消されます
  • 読み取り中にディスクドライブが取り外されている/マウントされていない

メソッドImageIO.read()はIOExceptionをスローします。

それを捕まえるか投げるかのどちらかを避ける方法はありません。

于 2012-11-27T06:39:58.020 に答える
2

私たちは彼とそれについていくらか詳細に話し合いました、そして彼は私が何が起こるかを正確に知っているなら私はフォールバックを試みる/キャッチすることに頼らずにそれを処理しようとするべきであるという線に沿って何かを言っていました。

インストラクターがIO例外を回避するためにテストする必要があると言っている場合は、彼が単に間違っているのではないかと心配しています。

  1. ほとんどのI/O操作IOExceptionは、チェックされた例外であるスローとして宣言されます。これらのメソッドを呼び出すとき、コードは例外を処理または伝播する必要があります。あなたは選択肢がありません。Java言語では、チェックされたすべての例外に対してこれが義務付けられています。

  2. 考えられるすべてのIOExceptionをテストすることは実用的ではありません。たとえば、このコードは失敗する可能性があります。

      if (f.exists() && f.canRead()) {
          os = new FileInputStream(f);
      }
    

    なんで?ハードディスクエラー、ネットワークエラー(ファイルがリモートマウントされたファイルシステム上にある場合)、強制アクセス制御の失敗など、コンストラクターがIOExceptionをスローする理由は他にもあるためです。多くの場合、根本的な状態は、ファイルを開こうとする以外の方法では検出できません。

  3. 次に、競合状態の問題があります。上記の例では、ファイルが読み取り可能であることをテストしてから開こうとするまでに、わずかな時間枠があります。その時間枠内で、他のスレッドまたは外部プロセスがファイルを削除するか、そのアクセスを変更して、開くことが失敗する可能性があります。その時間枠を閉じる方法はありません。

次に、なぜ例外を避けたいのかという問題があります。あなたの先生は「例外デニール」だと思います。つまり、「例外は例外的なものにのみ使用されるべきである」というアドバイスを非論理的な極端に受け止めている人々の1人です。

「例外は例外的なものにのみ使用する必要があります」というアドバイスは、基本的に、例外は高価であるため、使いすぎてはいけないと言っています。しかし、高価なのは相対的です。

この例では、toFile.exists()とtoの呼び出しFile.canRead()も、それぞれがシステムコールを伴うため、コストがかかります。これには、数千クロックサイクルかかります。さらに悪いことに、アプリケーションに異常がない限り、これら2つのテストは成功します...したがって、とにかくスローされない例外を回避するために、2つの不要なシステムコールを実行しました。これらのテストが失敗する可能性が高い(つまり> 50%)場合を除いて、テストをスキップし、オープンを試行して、例外が発生した場合はそれを処理する方が効率的です。


私は自分の教授にそのようなラベルを付けません。I / Oの複雑さについては特に話しませんでした。それは、私がそれを避けることができれば、それを避けるべきであるという、より一般的な用語でした。非常に避けられない例外があることを私は知りませんでした(そして彼はその詳細に立ち入りませんでした)。

わかった。だからあなたの教授はそれを言わなかった。彼にとって良かった。

そして、はい、それら複数の意味で避けられません。

.exists()チェックの使用を拒否することに関して、パフォーマンスへの影響はそれほど重要ですか?

はい。これを参照してください-Syscallオーバーヘッド

または、それが信じられない場合は、マイクロベンチマークを作成して測定してください。そして、それを例外をスローしてキャッチするオーバーヘッドと比較してください。

たとえば、デスクトップとモバイルなどの問題でしょうか。

いいえ。または、オペレーティングシステムが仮想メモリを使用して1つの「アプリ」が別の「アプリ」に干渉するのを防ぐモバイルの場合は確かにそうではありません。

トラブルシューティング/デバッグ(プログラムのクラッシュを回避しながら問題をより正確に特定できる場合)の明確さに対するトレードオフは、それだけの価値がありますか?

まあ、私はこのコードを主張します:

try (InputStream is = new FileInputStream(f)) {
    // use file
} catch (IOException ex) {
    System.err.println("IO error: ": ex.getMessage());
}

...これよりもシンプルで保守とデバッグが簡単です。

if (!f.exists()) {
    System.err.println("File " + f + " does not exist");
} else if (!f.isDirectory()) {
    System.err.println("File " + f + " is a directory");
} else if (!f.canRead()) {
    System.err.println("File " + f + " is not readable");
} ...
} else {
    try (InputStream is = new FileInputStream(f)) {
        // read
    } catch (IOException ex) {
        System.err.println("IO error: "+ ex.getMessage());
    }
}

同意しませんか?

于 2012-11-27T07:45:04.730 に答える
1

メソッドの宣言が表示された場合ImageIO.read:-

public static BufferedImage read(File input)
                          throws IOException

IOExceptionスローされることを宣言します。これはCheckedExceptionです。したがって、そのメソッドを呼び出すときは、で処理する必要がありますtry-catch block。または、使用しているメソッドでスローされるように宣言します。-

File f = new File("pic.png");
if (f.exists() && f.canRead()) {
    try {
        img = ImageIO.read(f);
    } catch (IOException e) {
        e.printStackTrace();
    }
} else { } // Error message.

ただし、上記のように処理していない場合は、メソッドのthrows句でそのメソッドを宣言して、に伝播し、caller処理できるようにする必要があります。

通常、チェックされた例外は処理するか、呼び出し元に伝播する必要があります。呼び出し元は徐々にmainメソッドに到達します。この場合、mainメソッドが処理しない場合は、によって処理されるためJVM、プログラムが終了します。

一般に、例外がスローされたメソッド自体で例外を処理し、必要に応じて適切なメッセージを呼び出し元に返すことをお勧めします。

于 2012-11-27T06:39:35.773 に答える