Apa perbedaan antara getPath (), getAbsolutePath (), dan getCanonicalPath () di Jawa?

583

Apa perbedaan antara getPath(), getAbsolutePath()dan getCanonicalPath()di Jawa?

Dan kapan saya menggunakan masing-masing?

knt
sumber
Jangan lupa Path.toAbsolutePath().normalize()yang merupakan jalan tengah yang baik antara jalur kanonik (nyata) dan jalur absolut saja.
eckes

Jawaban:

625

Pertimbangkan nama file ini:

C:\temp\file.txt - Ini adalah jalan, jalan absolut, dan jalan kanonik.

.\file.txt- Ini jalan. Itu bukan jalan absolut atau jalan kanonik.

C:\temp\myapp\bin\..\\..\file.txt- Ini adalah jalur dan jalur absolut. Itu bukan jalan kanonik.

Jalan kanonik selalu merupakan jalan absolut.

Mengubah dari jalur ke jalur kanonik menjadikannya absolut (biasanya menempel pada direktori kerja saat ini, jadi misalnya ./file.txtmenjadi c:/temp/file.txt). Path kanonik file hanya "memurnikan" path, menghapus dan menyelesaikan hal-hal seperti ..\dan menyelesaikan symlink (pada unix).

Perhatikan juga contoh berikut dengan 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());

Sementara kedua jalur merujuk ke lokasi yang sama, hasilnya akan sangat berbeda:

C:\Windows
C:\Windows\System32\drivers
tidak
sumber
11
FWIW, ini bukan C:\temp\file.txtmerupakan jalur kanonik - direktori temp mungkin berupa tautan lunak sistem file atau tautan keras (persimpangan di NTFS), dan file.txt mungkin merupakan tautan lunak. Saya tidak tahu apakah sistem file dapat membedakan tautan keras ke file.
Lawrence Dol
1
path tidak benar-benar mempertimbangkan masalah-masalah atau keberadaan salah satu komponen, hanya sintaksisnya.
escape-llc
Ya, jalur kanonik (tidak seperti jalur dinormalisasi) tidak mengenai sistem file.
eckes
1
Pada dasarnya, saya tidak bisa melihat alasan mengapa orang harus menggunakan getAbsolutePath()bukan getCanonicalPath(). Bahkan terlihat lebih baik karena kanonik secara otomatis menyelesaikan ../bagian - bagian itu.
Scadge
Jangan lupa bahwa getCanonicalPathmelempar IOExceptionsebentar getAbsolutePathtidak, jika ini pertimbangan.
Abandoned Cart
129

Cara terbaik yang saya temukan untuk merasakan hal-hal seperti ini adalah dengan mencobanya:

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

Output Anda akan seperti:

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

Jadi, getPath()memberi Anda jalan berdasarkan objek File, yang mungkin atau mungkin tidak relatif; getAbsolutePath()memberi Anda jalur absolut ke file; dan getCanonicalPath()memberi Anda jalur absolut unik ke file. Perhatikan bahwa ada sejumlah besar jalur absolut yang menunjuk ke file yang sama, tetapi hanya satu jalur kanonik.

Kapan harus menggunakan masing-masing? Tergantung pada apa yang ingin Anda capai, tetapi jika Anda mencoba melihat apakah keduanya Filesmenunjuk pada file yang sama pada disk, Anda dapat membandingkan jalur kanonik mereka. Hanya satu contoh.

dave4351
sumber
7
Dapat diperdebatkan bahwa Java salah menerapkan implementasi jalur "absolut"; itu benar-benar harus menghapus elemen jalur relatif di jalur absolut. Bentuk kanonik kemudian akan menghapus tautan atau persimpangan FS apa pun di jalur.
Lawrence Dol
but if you were trying to see if two Files are pointing at the same file on diskBagaimana? contoh tolong?
Asif Mushtaq
@UnKnown: Anda akan menggunakan jalur kanonik untuk itu.
Lawrence Dol
67

Pendeknya:

  • getPath()mendapat string jalur yang Fileobjeknya dibangun, dan itu mungkin direktori relatif saat ini.
  • getAbsolutePath() mendapatkan string path setelah menyelesaikannya terhadap direktori saat ini jika itu relatif, menghasilkan path yang sepenuhnya memenuhi syarat.
  • getCanonicalPath()mendapatkan string path setelah menyelesaikan path relatif terhadap direktori saat ini, dan menghapus path relatif ( .dan ..), dan semua sistem file link untuk mengembalikan path yang sistem file menganggap sarana kanonik untuk merujuk objek sistem file yang ditunjuknya.

Juga, masing-masing memiliki File yang setara yang mengembalikan Fileobjek yang sesuai .

Lawrence Dol
sumber
36

getPath()mengembalikan jalur yang digunakan untuk membuat Fileobjek. Nilai pengembalian ini tidak berubah berdasarkan lokasi dijalankan (hasil di bawah ini adalah untuk windows, pemisah jelas berbeda di tempat lain)

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()akan menyelesaikan jalur berdasarkan lokasi eksekusi atau drive. Jadi jika lari dari 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()tergantung sistem. Ini akan menyelesaikan lokasi unik yang dilambangkan oleh jalur. Jadi, jika Anda memiliki "." Di jalan mereka biasanya akan dihapus.

Seperti kapan menggunakannya. Itu tergantung pada apa yang ingin Anda capai. getPath()berguna untuk portabilitas. getAbsolutePath()berguna untuk menemukan lokasi sistem file, dan getCanonicalPath()sangat berguna untuk memeriksa apakah dua file itu sama.

Penjual Kaya
sumber
dapatkah Anda memberi saya contoh tentang ini? getCanonicalPath() is particularly useful to check if two files are the same.
Asif Mushtaq
20

Hal besar yang perlu Anda perhatikan adalah bahwa Filekelas mencoba untuk mewakili pandangan dari apa yang disebut Sun sebagai "nama path hierarkis" (pada dasarnya path seperti c:/foo.txtatau /usr/muggins). Inilah sebabnya mengapa Anda membuat file dalam hal jalur. Operasi yang Anda gambarkan adalah semua operasi pada "pathname" ini.

  • getPath()mengambil jalur tempat File dibuat dengan ( ../foo.txt)
  • getAbsolutePath()mengambil jalur tempat File dibuat, tetapi menyertakan informasi tentang direktori saat ini jika jalur relatif ( /usr/bobstuff/../foo.txt)
  • getCanonicalPath() mencoba mengambil representasi unik dari jalur absolut ke file. Ini menghilangkan tipuan dari ".." dan "." referensi ( /usr/foo.txt).

Catatan saya katakan upaya - dalam membentuk Canonical Path, VM dapat melempar IOException. Ini biasanya terjadi karena ia menjalankan beberapa operasi sistem file, yang salah satunya bisa gagal.

ayam mentega
sumber
3

Saya menemukan saya jarang perlu menggunakan getCanonicalPath()tetapi, jika diberi File dengan nama file yang ada dalam format DOS 8.3 di Windows, seperti java.io.tmpdirpengembalian properti Sistem, maka metode ini akan mengembalikan nama file "lengkap".

Matthew Wise
sumber