webentwicklung-frage-antwort-db.com.de

Prüfen Sie vor dem Aufruf von openFileInput, ob eine Datei vorhanden ist

Um eine Datei in Android aus dem privaten Speicherbereich Ihrer App zu lesen, verwenden Sie die FunktionopenFileInput()

Meine Frage ist: Gibt es eine Möglichkeit zu überprüfen, ob diese Datei vorhanden ist, bevor diese Funktion aufgerufen wird? Die Funktion kann eine FileNotFoundException werfen, aber ich möchte das gerne aufrufen und dann etwas tun, das auf einer try-catch basiert, ist eine schlechte Praxis.

Die Verwendung von File.exist() scheint eine seltsame Sache zu sein, da es erforderlich ist, eine Klasse zu instanziieren, und ich bin nicht sicher, ob durch das Übergeben des Dateinamens die Datei im privaten Bereich meines Telefons gefunden wird.

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

BEARBEITEN:

Hier ist auch eine andere Möglichkeit für Dateien im externen Speicher.

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

if(f.exists())
return;
46

Die Funktion kann eine FileNotFoundException durchlaufen, aber ich habe das Gefühl, dies aufzurufen und dann etwas zu tun, das auf einem try catch basiert, ist eine schlechte Praxis.

Ich stimme dir nicht zu. IMO, es wird getestet, ob die Datei vor dem Öffnen existiert, was eine schlechte Praxis ist. Vergleichen Sie diese beiden Versionen des Codes:

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

Version 1

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

Version 2

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

Es gibt eine Reihe von Problemen mit der ersten Version:

  • Version 1 führt einen zusätzlichen Systemaufruf durch, wenn Sie f.exists() aufrufen. Dies macht die erste Version im Durchschnitt langsamer, es sei denn, es besteht eine hohe Wahrscheinlichkeit, dass die Datei wird nicht existiert.

  • Version 1 hat eine Racebedingung. Wenn ein externer Prozess die Datei ungefähr zur gleichen Zeit löscht, könnte dies dazu führen, dass file.exists() true zurückgibt und der Konstruktor FileInputStreamFileNotFoundException auslöst. Dies ist die Art von Racebedingung, die ausgenutzt werden kann, um die Sicherheit zu gefährden, wenn die betreffende Datei sicherheitskritisch ist. (Tatsächlich gibt es auch eine zweite Racebedingung, bei der die Datei erstellt wird und file.exists() false zurückgibt, wenn ein nachfolgender Versuch, sie zu öffnen, erfolgreich ist. Diese Racebedingung ist jedoch wahrscheinlich harmlos.)

Ein weiteres Problem ist, dass FileInputStream als IOException deklariert wird. Das Testen, ob die Datei vorhanden ist, befasst sich nur mit einem der möglichen Fehlermodi. Ihr Code muss sowieso die anderen IOExceptions fangen und damit umgehen.


@Pieces kommentierte:

Ausnahmen sollten für den Fall sein, dass tatsächlich etwas schief geht, über das Sie keine Kontrolle haben. In diesem Fall habe ich die vollständige Kontrolle darüber.

Tatsächlich haben Sie keine vollständige Kontrolle darüber. Sicher nicht im allgemeinen Fall. Selbst in Ihrem speziellen Anwendungsfall ist die Rennbedingung theoretisch immer noch möglich.

Das eigentliche Problem bei dieser Denkweise ist jedoch, dass Sie am Ende durch die Rahmen springen, um Ausnahmen in Situationen zu vermeiden, in denen Ausnahmen/Ausnahmebehandlung die beste Lösung sind. Dies macht den Code komplizierter, weniger lesbar und möglicherweise langsamer und/oder zerbrechlicher.

Das normale Dogma sieht so aus:

"Ausnahmen sollten nur in Ausnahmesituationen verwendet werden".

Dies ist nicht dasselbe wie das, was Sie gesagt haben. Das Wort "außergewöhnlich" bedeutet eigentlich nur "nicht normal". Dies hat eine viel umfassendere Bedeutung als "etwas, über das Sie keine Kontrolle haben, geht tatsächlich schief".

Ich neige dazu, das Dogma wie folgt zu erweitern:

  • Ausnahmen sollten nicht werden für die normale Flusskontrolle verwendet.

  • Ausnahmen sollten nicht verwendet werden, wenn sie sich als zu teuer erweisen werden im Durchschnitt.

  • Ausnahmen sollte werden verwendet, wenn die Tests, die Sie verwenden würden, um sie zu vermeiden, nicht zuverlässig sind.

  • Ausnahmen sollte werden verwendet, wenn die Tests, mit denen Sie sie vermeiden würden, zu teuer sind im Durchschnitt.

  • Ausnahmen sollte werden verwendet, wenn sie Ihren Code erheblich vereinfachen (Modulo oben). Und das Kriterium für die Einfachheit ist, ob der Code von einem durchschnittlichen Java Programmierer gelesen werden kann.

(Anmerkung - "im Durchschnitt" und "z teuer" ...)

Jetzt kann man sich streiten, bis die Kühe nach Hause kommen wie außergewöhnlich ein Ereignis sein muss, aber ich gehe davon aus, dass es wirklich darum geht, die relative Einfachheit der Ansätze (im Kontext) gegen die abzuwägen durchschnittliche Leistungskosten (im Zusammenhang). Jede dogmatische Regel, die die Kompromisse und den Kontext nicht berücksichtigt, wird Ihnen in einigen Fällen Schaden zufügen.

30
Stephen C

Diese Arbeit für mich.

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

aber es kommt manchmal vor, dass eine Ausnahme die gleiche zurückgibt ... mit adb zu arbeiten.

0
rfellons