27

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

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

File.exist()クラスをインスタンス化する必要があり、ファイルの名前を渡すだけで携帯電話のプライベート領域でファイルが見つかるかどうかわからないため、使用するのも奇妙なことのように思えます。

4

3 に答える 3

55
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;
于 2012-01-15T03:35:24.253 に答える
32

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

同意しません。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。この競合状態はおそらく無害です。)

さらなる問題は、FileInputStreamがthrowingとして宣言されていることIOExceptionです。ファイルが存在するかどうかを確認するためのテストでは、考えられる障害モードの1つのみを処​​理します。あなたのコードはIOExceptionとにかく他のものを処理する必要があります。


@Piecesのコメント:

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

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

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

通常の教義は次のようになります。

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

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

私は次のように教義を拡張する傾向があります:

  • 通常のフロー制御には例外を使用しないでください。

  • 例外は、平均して高すぎることが判明する場合は使用しないでください

  • 例外回避するために使用するテストが信頼できない場合は、例外を使用する必要があります。

  • 例外を回避するために使用するテストが平均して高すぎる場合は、例外を使用する必要があります。

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

(注-「平均して」および「高すぎる」...)

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

于 2012-01-15T07:13:40.260 に答える
0

これは私のために働きます。

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

しかし、場合によっては、同じ例外が返されます...adbで動作します。

于 2016-02-29T16:55:41.297 に答える