Die java.nio.file.Files
API ist wirklich nett Verbesserung gegenüber der alten java.io.File
-Klasse, aber ein Detail scheint mir merkwürdig; mit Ausnahme von delete()
keine Methoden dokumentieren, dass sie NoSuchFileException
werfen können, und sogar delete()
sagt, dass dies optional ist.
Ich möchte in der Lage sein, zwischen Fehlern aufgrund fehlender Dateien und anderen IO-Problemen zu unterscheiden, aber es scheint, dass dies nicht garantiert ist.
Die Alternative, Files.exists()
und ähnliches vorher aufzurufen, birgt eine Race-Bedingung, wenn die Datei zwischen den beiden Operationen erstellt wird.
Kann ich erwarten, dass Methoden in Files
eine NoSuchFileException
erhöhen, wenn es angemessen ist? Wenn ja, wo ist das dokumentiert? Wenn nicht, wie kann ich sicher feststellen, dass der Fehler auf eine fehlende Datei zurückzuführen ist?
Beispiel: Unter Windows 7 mit Java 7.0.02 ist Files.readAllLines()
erhöht die NoSuchFileException
, obwohl dies nicht explizit dokumentiert ist:
%Vor%
Im Allgemeinen: Nein, Sie können den Methoden in java.nio.file.Files
nicht trauen, wenn Sie eine NoSuchFileException
erwartungsgemäß ausgeben, aber Sie können das überprüfen.
Wie Sie aus dem Stacktrace sehen können, verwendet Files
das FileSystemProvider
, um die Dateioperationen durchzuführen. Die FileSystemProvider
-Implementierungen sind eingeschränkt (wie der WindowsFileSystemProvider
) und wiederum viel nativen (C) Code verwenden. Zum Beispiel habe ich die NoSuchFileException
auf die WindowsException , die auf das Betriebssystem angewiesen ist, um ein ERROR_FILE_NOT_FOUND
oder ERROR_PATH_NOT_FOUND
zu melden. Ein anderes Beispiel ist die Route newInputStream
, die von ChannelInputStream bis WindowsChannelFactory zu WindowsNativeDispatcher.c , die schließlich die native Windows-Funktion CreateFileW .
Angesichts der Menge an Code, die nur für Windows beteiligt ist, sehe ich nicht, wie man das gleiche für zB Linux, das den Code hier und hier .
Nach meiner Erfahrung ist das Dateisystemverhalten von Linux (Posix) ziemlich konsistent, aber das Dateisystemverhalten von Windows (NT) ist nicht: Ich würde nicht davon ausgehen, dass sich Windows 7 genau wie Windows 8 verhält.
Abschließend noch eine Anmerkung zur Racebedingung: Kein Dateisystem, das ich kenne, garantiert, dass die in einem Verzeichnis aufgelisteten Dateien tatsächlich existieren (einige Dateien wurden möglicherweise bereits gelöscht, besonders wenn mehrere Threads mit Dateien im selben Verzeichnis arbeiten). Die Verwendung von Methoden wie Files.exists()
im Voraus ist meiner Erfahrung nach eine schlechte Idee, es sei denn, Sie werden eine Menge Ressourcen zuweisen (z. B. eine Verbindung zum Hochladen einer Datei erstellen). Wenn Sie mit Dateien arbeiten, ist es besser, davon auszugehen, dass alles in Ordnung ist, und Ausnahmen abzufangen und dann herauszufinden, was falsch ist. Z.B. Wenn Sie eine Datei lesen, öffnen Sie sie, ohne zu prüfen, ob die Datei existiert. Wenn Sie einen Fehler feststellen, prüfen Sie, ob die Datei zu Beginn existiert. Dadurch können viele E / A-Vorgänge eingespart werden, was wiederum die Leistung verbessert.
Die Klasse Files bietet zwei Löschmethoden .
Die Methode delete (Pfad) löscht die Datei oder löst eine Ausnahme aus, wenn der Löschvorgang fehlschlägt. Wenn die Datei beispielsweise nicht existiert, wird eine NoSuchFileException ausgelöst. Sie können die Ausnahme abfangen, um festzustellen, warum das Löschen wie folgt fehlgeschlagen ist:
%Vor%Die Methode deleteIfExists (Path) löscht auch die Datei. Wenn die Datei jedoch nicht existiert, wird keine Ausnahme ausgelöst. Wenn Sie mehrere Threads löschen, die Dateien löschen, und Sie keine Ausnahme auslösen möchten, weil ein Thread dies zuerst getan hat, ist das nicht möglich.
Hinweis: Die Ausnahmen NoSuchFileException und DirectoryNotEmptyException sind neue Ausnahmen, die in Java 7 eingeführt wurden.