Quelle est la différence entre getPath (), getAbsolutePath () et getCanonicalPath () en Java?

583

Quelle est la différence entre getPath(), getAbsolutePath()et getCanonicalPath()en Java?

Et quand dois-je utiliser chacun d'eux?

knt
la source
N'oubliez pas Path.toAbsolutePath().normalize()qui est un bon compromis entre le chemin canonique (réel) et le chemin absolu seul.
eckes

Réponses:

625

Considérez ces noms de fichiers:

C:\temp\file.txt - Ceci est un chemin, un chemin absolu et un chemin canonique.

.\file.txt- Ceci est un chemin. Ce n'est ni un chemin absolu ni un chemin canonique.

C:\temp\myapp\bin\..\\..\file.txt- C'est un chemin et un chemin absolu. Ce n'est pas un chemin canonique.

Un chemin canonique est toujours un chemin absolu.

La conversion d'un chemin vers un chemin canonique le rend absolu (généralement clou sur le répertoire de travail actuel, par exemple, ./file.txtdevient c:/temp/file.txt). Le chemin canonique d'un fichier "purifie" simplement le chemin, en supprimant et en résolvant des choses comme ..\et en résolvant les liens symboliques (sous unix).

Notez également l'exemple suivant avec 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());

Bien que les deux chemins se réfèrent au même emplacement, la sortie sera assez différente:

C:\Windows
C:\Windows\System32\drivers
non
la source
11
FWIW, ce n'est pas une donnée qui C:\temp\file.txtest un chemin canonique - le répertoire temporaire peut être un lien logiciel ou un lien dur de système de fichiers (une jonction dans NTFS), et file.txt peut être un lien logiciel. Je ne sais pas si les systèmes de fichiers peuvent distinguer les liens durs vers les fichiers.
Lawrence Dol
1
path ne prend pas vraiment en compte ces problèmes ou l'existence de l'un des composants, seulement sa syntaxe.
escape-llc
Il le fait, le chemin canonique (contrairement au chemin normalisé) atteint le système de fichiers.
eckes
1
Fondamentalement, je ne vois pas pourquoi on devrait utiliser à la getAbsolutePath()place de getCanonicalPath(). Il semble même meilleur car le canon canon résout automatiquement ces ../parties.
Scadge
N'oubliez pas que getCanonicalPathjeter un IOExceptionmoment getAbsolutePathne fait pas, si c'est une considération.
Panier abandonné
129

La meilleure façon que j'ai trouvée pour avoir une idée de ce genre de choses est de les essayer:

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

Votre sortie sera quelque chose comme:

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

Donc, getPath() vous donne le chemin basé sur l'objet File, qui peut être relatif ou non; getAbsolutePath()vous donne un chemin absolu vers le fichier; et getCanonicalPath()vous donne le chemin absolu unique vers le fichier. Notez qu'il existe un grand nombre de chemins absolus qui pointent vers le même fichier, mais un seul chemin canonique.

Quand utiliser chacun? Cela dépend de ce que vous essayez d'accomplir, mais si vous essayez de voir si deux Filespointent vers le même fichier sur le disque, vous pouvez comparer leurs chemins canoniques. Un seul exemple.

dave4351
la source
7
On peut soutenir que Java s'est trompé sur l'implémentation d'un chemin "absolu"; il aurait vraiment dû supprimer tous les éléments de chemin relatifs dans un chemin absolu. La forme canonique supprimerait alors tous les liens ou jonctions FS du chemin.
Lawrence Dol
but if you were trying to see if two Files are pointing at the same file on diskComment? exemple s'il vous plait?
Asif Mushtaq
@UnKnown: Vous utiliseriez le chemin canonique pour cela.
Lawrence Dol
67

En bref:

  • getPath()obtient la chaîne de chemin avec laquelle l' Fileobjet a été construit, et il peut s'agir du répertoire courant relatif.
  • getAbsolutePath() obtient la chaîne de chemin d'accès après l'avoir résolue par rapport au répertoire actuel si elle est relative, ce qui donne un chemin d'accès complet.
  • getCanonicalPath()obtient la chaîne de chemin d'accès après avoir résolu tout chemin relatif par rapport au répertoire en cours, et supprime tout cheminement relatif ( .et ..), et tous les liens du système de fichiers pour renvoyer un chemin que le système de fichiers considère comme le moyen canonique de référencer l'objet du système de fichiers vers lequel il pointe.

En outre, chacun d'eux a un équivalent de fichier qui renvoie l' Fileobjet correspondant .

Lawrence Dol
la source
36

getPath()renvoie le chemin utilisé pour créer l' Fileobjet. Cette valeur de retour n'est pas modifiée en fonction de l'emplacement où elle est exécutée (les résultats ci-dessous sont pour les fenêtres, les séparateurs sont évidemment différents ailleurs)

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()résoudra le chemin en fonction de l'emplacement d'exécution ou du lecteur. Donc, si exécutez à partir de 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()dépend du système. Il résoudra l'emplacement unique que le chemin représente. Donc, si vous avez des "." Dans le chemin, ils seront généralement supprimés.

Quant à savoir quand les utiliser. Cela dépend de ce que vous essayez de réaliser. getPath()est utile pour la portabilité. getAbsolutePath()est utile pour trouver l'emplacement du système de fichiers et getCanonicalPath()est particulièrement utile pour vérifier si deux fichiers sont identiques.

Vendeur riche
la source
pouvez-vous m'en donner un exemple? getCanonicalPath() is particularly useful to check if two files are the same.
Asif Mushtaq
20

La grande chose à comprendre est que la Fileclasse essaie de représenter une vue de ce que Sun aime appeler des "chemins d'accès hiérarchiques" (essentiellement un chemin comme c:/foo.txtou /usr/muggins). C'est pourquoi vous créez des fichiers en termes de chemins. Les opérations que vous décrivez sont toutes des opérations sur ce "chemin d'accès".

  • getPath()récupère le chemin avec lequel le fichier a été créé avec ( ../foo.txt)
  • getAbsolutePath()récupère le chemin avec lequel le fichier a été créé, mais inclut des informations sur le répertoire actuel si le chemin est relatif ( /usr/bobstuff/../foo.txt)
  • getCanonicalPath() tente de récupérer une représentation unique du chemin absolu du fichier. Cela élimine l'indirection de ".." et "." références ( /usr/foo.txt).

Notez que je dis tentatives - en formant un chemin canonique, la VM peut lancer un IOException. Cela se produit généralement car il exécute certaines opérations du système de fichiers, dont l'une pourrait échouer.

poulet au beurre
la source
3

Je trouve que j'ai rarement besoin d'utiliser getCanonicalPath()mais, si on me donne un fichier avec un nom de fichier au format DOS 8.3 sous Windows, tel que lejava.io.tmpdir retours de la propriété System, alors cette méthode retournera le nom de fichier "complet".

Matthew Wise
la source