¿Cuál es la diferencia entre getPath (), getAbsolutePath () y getCanonicalPath () en Java?

583

¿Cuál es la diferencia entre getPath(), getAbsolutePath()y getCanonicalPath()en Java?

¿Y cuándo uso cada uno?

knt
fuente
No olvide Path.toAbsolutePath().normalize()cuál es un buen término medio entre la ruta canónica (real) y la ruta absoluta solo.
eckes

Respuestas:

625

Considere estos nombres de archivo:

C:\temp\file.txt - Este es un camino, un camino absoluto y un camino canónico.

.\file.txt- Este es un camino. No es un camino absoluto ni un camino canónico.

C:\temp\myapp\bin\..\\..\file.txt- Este es un camino y un camino absoluto. No es un camino canónico.

Un camino canónico es siempre un camino absoluto.

La conversión de una ruta a una ruta canónica lo hace absoluto (generalmente se agrega al directorio de trabajo actual, por ejemplo, se ./file.txtconvierte en c:/temp/file.txt). La ruta canónica de un archivo simplemente "purifica" la ruta, eliminando y resolviendo cosas como ..\y resolviendo enlaces simbólicos (en unixes).

También tenga en cuenta el siguiente ejemplo 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());

Si bien ambas rutas se refieren a la misma ubicación, la salida será bastante diferente:

C:\Windows
C:\Windows\System32\drivers
nos
fuente
11
FWIW, no es un hecho que C:\temp\file.txtsea ​​una ruta canónica: el directorio temporal puede ser un enlace suave o un enlace duro del sistema de archivos (una unión en NTFS), y file.txt podría ser un enlace suave. No sé si los sistemas de archivos pueden distinguir los enlaces duros a los archivos.
Lawrence Dol
1
path realmente no considera esos problemas o la existencia de ninguno de los componentes, solo su sintaxis.
escape-llc
Lo hace, la ruta canónica (a diferencia de la ruta normalizada) golpea el sistema de archivos.
eckes
1
Básicamente, no puedo ver una razón por la que uno debería usar en getAbsolutePath()lugar de getCanonicalPath(). Incluso se ve mejor porque el canónico resuelve automáticamente esas ../partes.
Scadge
No olvide que getCanonicalPathtira un IOExceptionrato getAbsolutePathno, si esto es una consideración.
Carro abandonado el
129

La mejor manera que he encontrado para tener una idea de cosas como esta es probarlas:

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

Su salida será algo así como:

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

Por lo tanto, getPath()le proporciona la ruta basada en el objeto Archivo, que puede ser relativa o no; getAbsolutePath()le da una ruta absoluta al archivo; y getCanonicalPath()le da la ruta absoluta única al archivo. Tenga en cuenta que hay una gran cantidad de rutas absolutas que apuntan al mismo archivo, pero solo una ruta canónica.

¿Cuándo usar cada uno? Depende de lo que intente lograr, pero si intentara ver si dos Filesapuntan al mismo archivo en el disco, podría comparar sus rutas canónicas. Solo un ejemplo.

dave4351
fuente
77
Es discutible que Java haya equivocado su implementación de una ruta "absoluta"; Realmente debería haber eliminado cualquier elemento de ruta relativa en una ruta absoluta. La forma canónica luego eliminaría cualquier enlace o unión FS en la ruta.
Lawrence Dol
but if you were trying to see if two Files are pointing at the same file on disk¿Cómo? ejemplo por favor?
Asif Mushtaq
@UnKnown: usarías la ruta canónica para eso.
Lawrence Dol
67

En breve:

  • getPath()obtiene la cadena de ruta con la que Filese construyó el objeto, y puede ser un directorio actual relativo.
  • getAbsolutePath() obtiene la cadena de ruta después de resolverla en el directorio actual si es relativa, lo que resulta en una ruta totalmente calificada.
  • getCanonicalPath()obtiene la cadena de ruta después de resolver cualquier ruta relativa contra el directorio actual, y elimina cualquier ruta relativa ( .y ..), y cualquier enlace del sistema de archivos para devolver una ruta que el sistema de archivos considera el medio canónico para hacer referencia al objeto del sistema de archivos al que apunta.

Además, cada uno de estos tiene un archivo equivalente que devuelve el Fileobjeto correspondiente .

Lawrence Dol
fuente
36

getPath()devuelve la ruta utilizada para crear el Fileobjeto. Este valor de retorno no cambia en función de la ubicación en la que se ejecuta (los resultados a continuación son para ventanas, los separadores son obviamente diferentes en otros lugares)

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()resolverá la ruta en función de la ubicación o unidad de ejecución. Entonces, si se ejecuta desde 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()depende del sistema Resolverá la ubicación única que representa la ruta. Entonces, si tiene algún "." En la ruta, generalmente se eliminarán.

En cuanto a cuándo usarlos. Depende de lo que intentes lograr. getPath()Es útil para la portabilidad. getAbsolutePath()es útil para encontrar la ubicación del sistema de archivos y getCanonicalPath()es particularmente útil para verificar si dos archivos son iguales.

Vendedor rico
fuente
¿Me puede dar algún ejemplo de esto? getCanonicalPath() is particularly useful to check if two files are the same.
Asif Mushtaq
20

Lo importante para entender es que la Fileclase trata de representar una vista de lo que a Sun le gusta llamar "rutas jerárquicas" (básicamente, una ruta como c:/foo.txto /usr/muggins). Es por eso que crea archivos en términos de rutas. Las operaciones que está describiendo son todas operaciones sobre este "nombre de ruta".

  • getPath()recupera la ruta con la que se creó el archivo ( ../foo.txt)
  • getAbsolutePath()recupera la ruta con la que se creó el archivo, pero incluye información sobre el directorio actual si la ruta es relativa ( /usr/bobstuff/../foo.txt)
  • getCanonicalPath() intenta obtener una representación única de la ruta absoluta al archivo. Esto elimina la indirección de ".." y "." referencias ( /usr/foo.txt).

Tenga en cuenta que digo intentos : al formar una ruta canónica, la VM puede lanzar un IOException. Esto generalmente ocurre porque está realizando algunas operaciones del sistema de archivos, cualquiera de las cuales podría fallar.

pollo de mantequilla
fuente
3

Creo que rara vez necesito usarlo getCanonicalPath(), pero si se le da un archivo con un nombre de archivo que está en formato DOS 8.3 en Windows, como la java.io.tmpdirpropiedad del sistema, entonces este método devolverá el nombre de archivo "completo".

Matthew Wise
fuente