web-dev-qa-db-ja.com

openFileInputを呼び出す前にファイルが存在するかどうかを確認します

Android内のファイルをアプリのプライベートストレージ領域から読み取るには、functionopenFileInput()を使用します。

私の質問は、この関数を呼び出す前にこのファイルが存在するかどうかを確認する方法はありますか?関数はFileNotFoundExceptionをスローできますが、これを呼び出してtry-catchに基づいて何かをするのは悪い習慣です。

File.exist()を使用すると、クラスをインスタンス化する必要があり、ファイルの名前を渡すだけでそれが私の電話。

25
Pieces
public boolean fileExists(Context context, String filename) {    
    File file = context.getFileStreamPath(filename);
    if(file == null || !file.exists()) {
        return false;
    }
    return true;
}

編集:

また、外部ストレージにファイルを保存する別の方法もあります。

String fileUrl = "/appname/data.xml";
String file = Android.os.Environment.getExternalStorageDirectory().getPath() + fileUrl;
File f = new File(file);

if(f.exists())
return;
51

関数はFileNotFoundExceptionを介して実行できますが、これを呼び出して、try catchに基づいて何かを実行することは悪い習慣です。

同意しません。 IMO、開く前にファイルが存在するかどうかをテストしていますが、これは悪い習慣です。次の2つのバージョンのコードを比較してください。

File f = new File("someFile");
InputStream is;

バージョン#1

if (f.exists()) {
    is = new FileInputStream(f);
    ...
} else {
    System.err.println("Doesn't exist");
}

バージョン#2

try {
    is = new FileInputStream(f);
    ...
} catch (FileNotFoundException ex) {
    System.err.println("Doesn't exist");
}

最初のバージョンにはいくつかの問題があります:

  • バージョン#1は、f.exists()を呼び出すときに追加のシステムコールを作成します。これにより、ファイル存在しないが存在する可能性が高い場合を除き、平均して最初のバージョンが遅くなります。

  • バージョン#1には競合状態があります。外部プロセスがファイルをほぼ同時に削除した場合、file.exists()がtrueを返し、FileInputStreamコンストラクターがFileNotFoundExceptionをスローする可能性があります。これは、問題のファイルがセキュリティ上重要な場合に、セキュリティを破るために悪用される可能性のある競合状態です。

    (実際には、2番目の競合状態もあります。ファイルの作成中にfile.exists()を呼び出すと、falseが返されることがあります。その場合、new FileInputStreamであってもエラーメッセージが出力されます。成功した可能性があります。この競合状態はおそらく無害です。)

さらなる問題は、FileInputStreamIOExceptionをスローするように宣言されていることです。ファイルが存在するかどうかを確認するためのテストは、考えられる障害モードの1つのみを扱います。あなたのコードはとにかく他のIOExceptionsを扱わなければならないでしょう。


@Piecesがコメントしました:

例外は、あなたが制御できない何かが実際にうまくいかない場合のためのものです。この場合、私はそれを完全に制御できます。

実際、それを完全に制御することはできません。確かに一般的なケースではありません。特定のユースケースでも、理論上は競合状態が発生する可能性があります。

しかし、この考え方の本当の問題は、例外/例外処理がbestソリューションである状況で例外を回避するためにフープを飛び越えてしまうことです。これにより、コードが複雑になり、読みにくくなり、速度が低下したり、壊れやすくなったりする可能性があります。

通常のドグマは次のようになります。

"例外は例外的な状況でのみ使用する必要があります"

これはあなたが言ったことと同じではありません。 「例外的」という言葉は、実際には「通常ではない」という意味です。これは、「あなたが制御できない何かが実際にうまくいかない」よりもはるかに広い意味を持っています。

私は次のようにドグマを拡張する傾向があります:

  • 例外すべきではない通常のフロー制御に使用されます。

  • 例外すべきではない彼らが高すぎると証明する場合に使用平均で

  • 例外すべきそれらを回避するために使用するテストが信頼できない場合に使用します。

  • 例外すべきそれらを回避するために使用するテストが高すぎる場合平均を使用します。

  • 例外すべき(上記を法として)コードを大幅に簡略化する場合に使用します。そして、単純さの基準は、コードが平均的なJavaプログラマーによって読み取り可能かどうかです。

(注-「平均的」および「あまりに高い」...)

これで、牛が家に帰るまで議論することができますどれほど例外的イベントにする必要がありますが、これは実際には、(コンテキストにおける)アプローチの相対的な単純さと、平均のパフォーマンスコスト(コンテキスト内)。トレードオフとコンテキストを考慮に入れない独断的なルールは、場合によっては害を及ぼします。

32
Stephen C

この仕事は私にとって。

try {
  FileInputStream fis = openFileInput(String filename);
  // ... do something
try {
    fis.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
} catch (FileNotFoundException e) { 
  e.printStackTrace();
}

しかし、ときどき、同じように例外が返されます... adbで作業しています。

0
rfellons