Antworten:
Betrachten Sie diese Dateinamen:
C:\temp\file.txt
- Dies ist ein Pfad, ein absoluter Pfad und ein kanonischer Pfad.
.\file.txt
- Dies ist ein Weg. Es ist weder ein absoluter noch ein kanonischer Weg.
C:\temp\myapp\bin\..\\..\file.txt
- Dies ist ein Pfad und ein absoluter Pfad. Es ist kein kanonischer Weg.
Ein kanonischer Pfad ist immer ein absoluter Pfad.
Das Konvertieren von einem Pfad in einen kanonischen Pfad macht ihn absolut (normalerweise wird das aktuelle Arbeitsverzeichnis angeheftet, z . B. ./file.txt
wird es c:/temp/file.txt
). Der kanonische Pfad einer Datei "bereinigt" lediglich den Pfad, indem ..\
Dinge wie Symlinks (unter Unixen) entfernt und aufgelöst werden .
Beachten Sie auch das folgende Beispiel mit nio.Paths:
String canonical_path_string = "C:\\Windows\\System32\\";
String absolute_path_string = "C:\\Windows\\System32\\drivers\\..\\";
System.out.println(Paths.get(canonical_path_string).getParent());
System.out.println(Paths.get(absolute_path_string).getParent());
Während sich beide Pfade auf denselben Speicherort beziehen, ist die Ausgabe sehr unterschiedlich:
C:\Windows
C:\Windows\System32\drivers
C:\temp\file.txt
es sich um einen kanonischen Pfad handelt. Das temporäre Verzeichnis kann ein Softlink oder ein Hardlink des Dateisystems (eine Verbindung in NTFS) sein, und file.txt kann ein Softlink sein. Ich weiß nicht, ob Dateisysteme Hardlinks zu Dateien unterscheiden können.
getAbsolutePath()
statt getCanonicalPath()
. Es sieht sogar besser aus, weil der Kanonische diese ../
Teile automatisch auflöst .
getCanonicalPath
Würfe eine IOException
Weile getAbsolutePath
nicht werfen , wenn dies eine Überlegung ist.
Der beste Weg, ein Gefühl für solche Dinge zu bekommen, ist, sie auszuprobieren:
import java.io.File;
public class PathTesting {
public static void main(String [] args) {
File f = new File("test/.././file.txt");
System.out.println(f.getPath());
System.out.println(f.getAbsolutePath());
try {
System.out.println(f.getCanonicalPath());
}
catch(Exception e) {}
}
}
Ihre Ausgabe wird ungefähr so aussehen:
test\..\.\file.txt
C:\projects\sandbox\trunk\test\..\.\file.txt
C:\projects\sandbox\trunk\file.txt
Also, getPath()
haben Sie den Pfad basierend auf dem File - Objekt, das nicht relativ sein kann oder nicht; getAbsolutePath()
gibt Ihnen einen absoluten Pfad zur Datei; und getCanonicalPath()
gibt Ihnen den eindeutigen absoluten Pfad zur Datei. Beachten Sie, dass es eine große Anzahl absoluter Pfade gibt, die auf dieselbe Datei verweisen, aber nur einen kanonischen Pfad.
Wann sollte jeder verwendet werden? Hängt davon ab, was Sie erreichen möchten. Wenn Sie jedoch versuchen möchten, festzustellen, ob zwei Files
auf dieselbe Datei auf der Festplatte zeigen, können Sie ihre kanonischen Pfade vergleichen. Nur ein Beispiel.
but if you were trying to see if two Files are pointing at the same file on disk
Wie? Beispiel bitte?
Zusamenfassend:
getPath()
Ruft die Pfadzeichenfolge ab, mit der das File
Objekt erstellt wurde, und es kann sich um ein relativ aktuelles Verzeichnis handeln.getAbsolutePath()
Ruft die Pfadzeichenfolge ab, nachdem sie im aktuellen Verzeichnis aufgelöst wurde, wenn sie relativ ist, was zu einem vollständig qualifizierten Pfad führt.getCanonicalPath()
Ruft die Pfadzeichenfolge ab, nachdem ein relativer Pfad für das aktuelle Verzeichnis aufgelöst wurde, und entfernt alle relativen Pfade ( .
und ..
) sowie alle Dateisystemverknüpfungen, um einen Pfad zurückzugeben, den das Dateisystem als kanonisches Mittel betrachtet, um auf das Dateisystemobjekt zu verweisen, auf das es verweist.Außerdem verfügt jede dieser Dateien über ein Dateiäquivalent, das das entsprechende File
Objekt zurückgibt .
getPath()
Gibt den Pfad zurück, der zum Erstellen des File
Objekts verwendet wurde. Dieser Rückgabewert wird nicht basierend auf dem Speicherort geändert (die folgenden Ergebnisse gelten für Fenster, Trennzeichen unterscheiden sich offensichtlich an anderer Stelle).
File f1 = new File("/some/path");
String path = f1.getPath(); // will return "\some\path"
File dir = new File("/basedir");
File f2 = new File(dir, "/some/path");
path = f2.getPath(); // will return "\basedir\some\path"
File f3 = new File("./some/path");
path = f3.getPath(); // will return ".\some\path"
getAbsolutePath()
Löst den Pfad basierend auf dem Ausführungsort oder dem Laufwerk auf. Also wenn laufen von c:\test
:
path = f1.getAbsolutePath(); // will return "c:\some\path"
path = f2.getAbsolutePath(); // will return "c:\basedir\some\path"
path = f3.getAbsolutePath(); // will return "c:\test\.\basedir\some\path"
getCanonicalPath()
ist systemabhängig. Dadurch wird der eindeutige Speicherort aufgelöst, den der Pfad darstellt. Wenn Sie also "." Im Pfad haben, werden diese normalerweise entfernt.
Wann man sie benutzt. Es hängt davon ab, was Sie erreichen wollen. getPath()
ist nützlich für die Portabilität. getAbsolutePath()
ist nützlich, um den Speicherort des Dateisystems zu finden, und getCanonicalPath()
ist besonders nützlich, um zu überprüfen, ob zwei Dateien identisch sind.
getCanonicalPath() is particularly useful to check if two files are the same.
Das Wichtigste ist, dass die File
Klasse versucht, eine Ansicht dessen darzustellen, was Sun gerne als "hierarchische Pfadnamen" bezeichnet (im Grunde ein Pfad wie c:/foo.txt
oder /usr/muggins
). Aus diesem Grund erstellen Sie Dateien in Form von Pfaden. Die Operationen, die Sie beschreiben, sind alle Operationen auf diesen "Pfadnamen".
getPath()
Ruft den Pfad ab, mit dem die Datei erstellt wurde ( ../foo.txt
)getAbsolutePath()
Ruft den Pfad ab, mit dem die Datei erstellt wurde, enthält jedoch Informationen zum aktuellen Verzeichnis, wenn der Pfad relativ ist ( /usr/bobstuff/../foo.txt
)getCanonicalPath()
versucht , eine eindeutige Darstellung des absoluten Pfads zur Datei abzurufen. Dies eliminiert die Indirektion von ".." und "." Referenzen ( /usr/foo.txt
).Hinweis Ich sage Versuche - beim Bilden eines kanonischen Pfades kann die VM einen werfen IOException
. Dies tritt normalerweise auf, weil einige Dateisystemoperationen ausgeführt werden, von denen jede fehlschlagen kann.
Ich finde, ich muss selten verwenden, getCanonicalPath()
aber wenn eine Datei mit einem Dateinamen im DOS 8.3-Format unter Windows angegeben wird, wie z. B. die java.io.tmpdir
Rückgabe der Systemeigenschaft, gibt diese Methode den "vollständigen" Dateinamen zurück.
Path.toAbsolutePath().normalize()
was ein guter Mittelweg zwischen kanonischem (realem) Pfad und absolutem Pfad allein ist.