Qual è la differenza tra getPath (), getAbsolutePath () e getCanonicalPath () in Java?


583

Qual è la differenza tra getPath(), getAbsolutePath()e getCanonicalPath()in Java?

E quando uso ognuno?


Non dimenticare Path.toAbsolutePath().normalize()quale è una buona via di mezzo tra percorso canonico (reale) e percorso assoluto da solo.
Devo dire che il

Risposte:


625

Considera questi nomi di file:

C:\temp\file.txt - Questo è un percorso, un percorso assoluto e un percorso canonico.

.\file.txt- Questo è un percorso. Non è né un percorso assoluto né un percorso canonico.

C:\temp\myapp\bin\..\\..\file.txt- Questo è un percorso e un percorso assoluto. Non è un percorso canonico.

Un percorso canonico è sempre un percorso assoluto.

La conversione da un percorso a un percorso canonico lo rende assoluto (di solito virata sulla directory di lavoro corrente, ad esempio ./file.txtdiventa c:/temp/file.txt). Il percorso canonico di un file "purifica" il percorso, rimuovendo e risolvendo cose come ..\e risolvendo collegamenti simbolici (su unix).

Nota anche il seguente esempio con 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());

Mentre entrambi i percorsi si riferiscono alla stessa posizione, l'output sarà piuttosto diverso:

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

11
FWIW, non è scontato che si C:\temp\file.txttratti di un percorso canonico: la directory temporanea potrebbe essere un collegamento software del file system o un collegamento reale (una giunzione in NTFS) e file.txt potrebbe essere un collegamento software. Non so se i file system possano distinguere i collegamenti reali ai file.
Lawrence Dol,

1
path non considera realmente quei problemi o l'esistenza di nessuno dei componenti, ma solo la sua sintassi.
escape-llc

Lo fa, il percorso canonico (a differenza del percorso normalizzato) colpisce il file system.
Devo dire che il

1
Fondamentalmente, non riesco a vedere un motivo per cui si dovrebbe usare al getAbsolutePath()posto di getCanonicalPath(). Sembra persino migliore perché quello canonico risolve automaticamente quelle ../parti.
Scadge,

Non dimenticate che getCanonicalPathgetta un IOExceptionpo ' getAbsolutePathnon lo fa, se questa è una considerazione.
Carrello abbandonato

129

Il modo migliore che ho trovato per avere un'idea di cose come questa è provarle:

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

Il tuo output sarà simile a:

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

Quindi, getPath()ti dà il percorso basato sull'oggetto File, che può essere o non essere relativo; getAbsolutePath()ti dà un percorso assoluto per il file; e getCanonicalPath()ti dà il percorso assoluto univoco al file. Si noti che esiste un numero enorme di percorsi assoluti che puntano allo stesso file, ma solo un percorso canonico.

Quando usarli? Dipende da cosa stai cercando di realizzare, ma se stavi cercando di vedere se dueFiles puntano allo stesso file su disco, potresti confrontare i loro percorsi canonici. Solo un esempio.


7
È discutibile che Java abbia sbagliato l'implementazione di un percorso "assoluto"; avrebbe dovuto rimuovere qualsiasi elemento relativo del percorso in un percorso assoluto. La forma canonica rimuove quindi eventuali collegamenti o giunzioni FS nel percorso.
Lawrence Dol

but if you were trying to see if two Files are pointing at the same file on diskCome? esempio per favore?
Asif Mushtaq,

@UnKnown: per questo useresti il ​​percorso canonico.
Lawrence Dol,

67

In breve:

  • getPath()ottiene la stringa del percorso con cui è Filestato costruito l' oggetto e può essere la directory corrente relativa.
  • getAbsolutePath() ottiene la stringa del percorso dopo averla risolta nella directory corrente se è relativa, risultando in un percorso completo.
  • getCanonicalPath()ottiene la stringa del percorso dopo aver risolto qualsiasi percorso relativo rispetto alla directory corrente e rimuove qualsiasi percorso relativo ( .e ..) e qualsiasi collegamento al file system per restituire un percorso che il file system considera i mezzi canonici per fare riferimento all'oggetto del file system a cui punta.

Inoltre, ognuno di questi ha un equivalente File che restituisce l' Fileoggetto corrispondente .


36

getPath()restituisce il percorso utilizzato per creare l' Fileoggetto. Questo valore di ritorno non viene modificato in base alla posizione in cui viene eseguito (i risultati seguenti sono per Windows, i separatori sono ovviamente diversi altrove)

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()risolverà il percorso in base alla posizione o all'unità di esecuzione. Quindi, se eseguito da 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()dipende dal sistema. Risolverà la posizione unica rappresentata dal percorso. Quindi, se hai "." Nel percorso, questi verranno generalmente rimossi.

Quanto a quando usarli. Dipende da cosa stai cercando di ottenere. getPath()è utile per la portabilità. getAbsolutePath()è utile per trovare la posizione del file system ed getCanonicalPath()è particolarmente utile per verificare se due file sono uguali.


puoi darmi qualche esempio di questo? getCanonicalPath() is particularly useful to check if two files are the same.
Asif Mushtaq,

20

La cosa più grande da tenere a mente è che la Fileclasse cerca di rappresentare una visione di ciò che a Sun piace chiamare "nomi gerarchici" (fondamentalmente un percorso come c:/foo.txto /usr/muggins). Questo è il motivo per cui crei file in termini di percorsi. Le operazioni che stai descrivendo sono tutte operazioni su questo "nome percorso".

  • getPath()recupera il percorso con cui è stato creato il file ( ../foo.txt)
  • getAbsolutePath()recupera il percorso con cui è stato creato il file, ma include informazioni sulla directory corrente se il percorso è relativo ( /usr/bobstuff/../foo.txt)
  • getCanonicalPath() tenta di recuperare una rappresentazione univoca del percorso assoluto del file. Questo elimina il riferimento indiretto da ".." e "." referenze ( /usr/foo.txt).

Nota dico tentativi : nel formare un Percorso canonico, la VM può lanciare un IOException. Questo di solito si verifica perché sta eseguendo alcune operazioni del filesystem, ognuna delle quali potrebbe non riuscire.


3

Trovo che raramente ho bisogno di usare getCanonicalPath()ma, se viene dato un file con un nome file che è in formato DOS 8.3 su Windows, come la java.io.tmpdirproprietà System restituisce, questo metodo restituirà il nome file "completo".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.