Jaka jest różnica między getPath (), getAbsolutePath () i getCanonicalPath () w Javie?


583

Jaka jest różnica pomiędzy getPath(), getAbsolutePath()oraz getCanonicalPath()w Java?

A kiedy z nich korzystam?


Nie zapominaj, Path.toAbsolutePath().normalize()który jest dobry środek między kanoniczną (prawdziwą) ścieżką a samą ścieżką absolutną.
— eckes

Odpowiedzi:


625

Rozważ te nazwy plików:

C:\temp\file.txt - To jest ścieżka, ścieżka absolutna i ścieżka kanoniczna.

.\file.txt- To jest ścieżka. Nie jest to ani ścieżka absolutna, ani kanoniczna.

C:\temp\myapp\bin\..\\..\file.txt- To jest ścieżka i ścieżka absolutna. To nie jest ścieżka kanoniczna.

Ścieżka kanoniczna jest zawsze ścieżką absolutną.

Konwersja ścieżki na ścieżkę kanoniczną czyni ją absolutną (zwykle dołącza się do bieżącego katalogu roboczego, np. ./file.txtStaje się c:/temp/file.txt). Kanoniczna ścieżka pliku po prostu „oczyszcza” ścieżkę, usuwając i rozwiązując takie rzeczy, jak ..\i rozwiązując dowiązania symboliczne (w unixach).

Zwróć również uwagę na następujący przykład z 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());

Podczas gdy obie ścieżki odnoszą się do tej samej lokalizacji, dane wyjściowe będą zupełnie inne:

C:\Windows
C:\Windows\System32\drivers

11
FWIW, to nie jest dana C:\temp\file.txtścieżka kanoniczna - katalog tymczasowy może być miękkim dowiązaniem systemu plików lub dowiązaniem twardym (połączenie w NTFS), a file.txt może być dowiązaniem miękkim. Nie wiem, czy systemy plików potrafią odróżnić twarde linki do plików.
— Lawrence Dol

1
ścieżka tak naprawdę nie bierze pod uwagę tych problemów lub istnienia któregokolwiek ze składników, a jedynie jego składnię.
— escape-llc

Tak, ścieżka kanoniczna (w przeciwieństwie do ścieżki znormalizowanej) uderza w system plików.
— eckes

1
Zasadniczo nie widzę powodu, dla którego należy użyć getAbsolutePath()zamiast getCanonicalPath(). Wygląda nawet lepiej, ponieważ kanoniczny automatycznie rozwiązuje te ../części.
— Scadge

Nie zapominaj, że getCanonicalPathrzuca IOExceptionchwilę getAbsolutePathnie, jeśli jest to uwaga.
— Opuszczony

129

Najlepszym sposobem, aby znaleźć takie rzeczy, jest wypróbowanie ich:

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) {}
    }
}

Twój wynik będzie podobny do:

test\..\.\file.txt
C:\projects\sandbox\trunk\test\..\.\file.txt
C:\projects\sandbox\trunk\file.txt

Więc getPath()daje ścieżkę opartą na obiekt pliku, który może lub nie może być względne; getAbsolutePath()daje bezwzględną ścieżkę do pliku; igetCanonicalPath() daje unikalną bezwzględną ścieżkę do pliku. Zauważ, że istnieje ogromna liczba ścieżek bezwzględnych, które wskazują na ten sam plik, ale tylko jedna ścieżka kanoniczna.

Kiedy używać każdego z nich? Zależy od tego, co próbujesz osiągnąć, ale jeśli próbujesz sprawdzić, czy dwa Fileswskazują na ten sam plik na dysku, możesz porównać ich ścieżki kanoniczne. Tylko jeden przykład.


7
Można argumentować, że Java źle zrozumiała implementację ścieżki „absolutnej”; naprawdę powinien usunąć wszelkie względne elementy ścieżki w ścieżce bezwzględnej. Forma kanoniczna usunąłaby wówczas wszelkie łącza FS lub skrzyżowania na ścieżce.
— Lawrence Dol

but if you were trying to see if two Files are pointing at the same file on diskW jaki sposób? przykład proszę?
— Asif Mushtaq

@UnKnown: Użyłbyś do tego kanonicznej ścieżki.
— Lawrence Dol

67

W skrócie:

  • getPath()pobiera ciąg ścieżki, z którym Fileobiekt został zbudowany, i może być względnym bieżącym katalogiem.
  • getAbsolutePath() pobiera ciąg ścieżki po rozwiązaniu go względem bieżącego katalogu, jeśli jest względny, co daje w pełni kwalifikowaną ścieżkę.
  • getCanonicalPath()pobiera ciąg ścieżki po rozwiązaniu ścieżki względnej względem bieżącego katalogu i usuwa wszelkie ścieżki względne ( .i ..), a także wszelkie łącza systemu plików, aby zwrócić ścieżkę, którą system plików uważa za kanoniczny sposób odniesienia do obiektu systemu plików, na który wskazuje.

Ponadto każdy z nich ma odpowiednik Plik, który zwraca odpowiedni Fileobiekt.


36

getPath()zwraca ścieżkę użytą do utworzenia Fileobiektu. Ta wartość zwracana nie jest zmieniana w zależności od miejsca, w którym jest uruchomiona (wyniki poniżej dotyczą okien, separatory są oczywiście inne w innym miejscu)

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()rozpozna ścieżkę na podstawie lokalizacji wykonania lub dysku. Więc jeśli uruchomisz z 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()zależy od systemu. Rozwiąże unikalną lokalizację reprezentowaną przez ścieżkę. Więc jeśli masz jakieś „.” Na ścieżce, będą one zazwyczaj usuwane.

Kiedy z nich korzystać. To zależy od tego, co próbujesz osiągnąć. getPath()jest przydatny do przenoszenia. getAbsolutePath()przydaje się do znalezienia lokalizacji systemu plików, a getCanonicalPath()szczególnie sprawdza się, czy dwa pliki są takie same.


czy możesz mi to podać? getCanonicalPath() is particularly useful to check if two files are the same.
— Asif Mushtaq

20

Najważniejszą rzeczą, aby rozejrzeć się po głowie jest to, że File klasa próbuje przedstawić pogląd, który Sun nazywa „ścieżkami hierarchicznymi” (w zasadzie ścieżką podobną do c:/foo.txtlub /usr/muggins). Dlatego tworzysz pliki pod względem ścieżek. Operacje, które opisujesz, to wszystkie operacje na tej „ścieżce”.

  • getPath() pobiera ścieżkę, z którą plik został utworzony (../foo.txt )
  • getAbsolutePath()pobiera ścieżkę, z którą plik został utworzony, ale zawiera informacje o bieżącym katalogu, jeśli ścieżka jest względna ( /usr/bobstuff/../foo.txt)
  • getCanonicalPath() próbowanie pobrać unikalną reprezentację bezwzględnej ścieżki do pliku. Eliminuje to pośrednictwo z „..” i „.” referencje ( /usr/foo.txt).

Uwaga: Mówię próby - tworząc Kanoniczną Ścieżkę, VM może rzucić IOException. Zwykle dzieje się tak, ponieważ wykonuje niektóre operacje na systemie plików, z których każda może się nie powieść.


3

Uważam, że rzadko muszę go używać, getCanonicalPath()ale jeśli otrzymam plik z nazwą pliku w formacie DOS 8.3 w systemie Windows, taki jak java.io.tmpdirzwraca właściwość System, wówczas ta metoda zwróci „pełną” nazwę pliku.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.