Qual é a diferença entre getPath (), getAbsolutePath () e getCanonicalPath () em Java?


583

Qual é a diferença entre getPath(), getAbsolutePath()e getCanonicalPath()em Java?

E quando eu uso cada um?


Não esqueça Path.toAbsolutePath().normalize()qual é um bom meio termo entre o caminho canônico (real) e o caminho absoluto sozinho.
— Eckes

Respostas:


625

Considere estes nomes de arquivos:

C:\temp\file.txt - Este é um caminho, um caminho absoluto e um caminho canônico.

.\file.txt- Este é um caminho. Não é um caminho absoluto nem um caminho canônico.

C:\temp\myapp\bin\..\\..\file.txt- Este é um caminho e um caminho absoluto. Não é um caminho canônico.

Um caminho canônico é sempre um caminho absoluto.

A conversão de um caminho para um caminho canônico o torna absoluto (geralmente adere ao diretório de trabalho atual, por exemplo, ./file.txttorna-se c:/temp/file.txt). O caminho canônico de um arquivo apenas "purifica" o caminho, removendo e resolvendo coisas como ..\e resolvendo links simbólicos (em unixes).

Observe também o exemplo a seguir com 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());

Enquanto os dois caminhos se referem ao mesmo local, a saída será bem diferente:

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

11
FWIW, não é um dado C:\temp\file.txtcanônico - o diretório temporário pode ser um link flexível do sistema de arquivos ou um link físico (uma junção no NTFS), e file.txt pode ser um link flexível. Não sei se os sistemas de arquivos podem distinguir links físicos para arquivos.
— Lawrence Dol

1
O caminho não considera realmente esses problemas ou a existência de nenhum dos componentes, apenas a sintaxe.
— escape-llc

Sim, o caminho canônico (diferente do caminho normalizado) atinge o sistema de arquivos.
— Eckes

1
Basicamente, não vejo uma razão pela qual alguém deva usar em getAbsolutePath()vez de getCanonicalPath(). Até parece melhor porque o canônico resolve essas ../partes automaticamente .
— Scadge

Não se esqueça que getCanonicalPathjoga um IOExceptiontempo getAbsolutePathnão, se isso é uma consideração.
— Carrinho abandonado

129

A melhor maneira que encontrei para experimentar coisas assim é experimentá-las:

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

Sua saída será algo como:

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

Portanto, getPath()fornece o caminho com base no objeto File, que pode ou não ser relativo; getAbsolutePath()fornece um caminho absoluto para o arquivo; egetCanonicalPath() fornece o caminho absoluto exclusivo para o arquivo. Observe que há um grande número de caminhos absolutos que apontam para o mesmo arquivo, mas apenas um caminho canônico.

Quando usar cada um? Depende do que você está tentando realizar, mas se você está tentando ver se dois Filesestão apontando para o mesmo arquivo no disco, você pode comparar seus caminhos canônicos. Apenas um exemplo.


7
É discutível que Java tenha entendido errado a implementação de um caminho "absoluto"; realmente deveria ter removido qualquer elemento relativo do caminho em um caminho absoluto. A forma canônica removeria todos os links ou junções FS no caminho.
— Lawrence Dol

but if you were trying to see if two Files are pointing at the same file on diskQuão? exemplo por favor?
— Asif Mushtaq

@ Desconhecido: Você usaria o caminho canônico para isso.
— Lawrence Dol

67

Em resumo:

  • getPath()obtém a cadeia de caminho com a qual o Fileobjeto foi construído e pode ser o diretório atual relativo.
  • getAbsolutePath() obtém a sequência do caminho após resolvê-la no diretório atual, se for relativo, resultando em um caminho completo.
  • getCanonicalPath()obtém a cadeia de caminho após resolver qualquer caminho relativo no diretório atual e remove qualquer caminho relativo ( .e ..) e qualquer link do sistema de arquivos para retornar um caminho que o sistema de arquivos considera os meios canônicos para referenciar o objeto do sistema de arquivos para o qual aponta.

Além disso, cada um deles possui um arquivo equivalente, que retorna o Fileobjeto correspondente .


36

getPath()retorna o caminho usado para criar o Fileobjeto. Esse valor de retorno não é alterado com base no local em que é executado (os resultados abaixo são para janelas, os separadores são obviamente diferentes em outros 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á o caminho com base no local de execução ou na unidade. Portanto, se executado a 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()depende do sistema. Ele resolverá o local exclusivo que o caminho representa. Portanto, se você tiver algum "." S no caminho, eles normalmente serão removidos.

Quanto a quando usá-los. Depende do que você está tentando alcançar. getPath()é útil para portabilidade. getAbsolutePath()é útil para encontrar o local do sistema de arquivos e getCanonicalPath()é particularmente útil para verificar se dois arquivos são iguais.


você pode me dar um exemplo disso? getCanonicalPath() is particularly useful to check if two files are the same.
— Asif Mushtaq

20

O mais importante é que a Fileclasse tenta representar uma visão do que a Sun gosta de chamar de "nomes de caminhos hierárquicos" (basicamente um caminho como c:/foo.txtou /usr/muggins). É por isso que você cria arquivos em termos de caminhos. As operações que você está descrevendo são todas operações sobre esse "nome do caminho".

  • getPath()busca o caminho com o qual o arquivo foi criado ( ../foo.txt)
  • getAbsolutePath()busca o caminho com o qual o arquivo foi criado, mas inclui informações sobre o diretório atual se o caminho for relativo ( /usr/bobstuff/../foo.txt)
  • getCanonicalPath() tenta buscar uma representação exclusiva do caminho absoluto para o arquivo. Isso elimina a indireção de ".." e "." referências ( /usr/foo.txt).

Note que digo tentativas - ao formar um caminho canônico, a VM pode lançar um IOException. Isso geralmente ocorre porque está executando algumas operações do sistema de arquivos, qualquer uma das quais pode falhar.


3

Acho que raramente preciso usar getCanonicalPath(), mas, se for fornecido um arquivo com um nome de arquivo no formato DOS 8.3 no Windows, como a java.io.tmpdirpropriedade System retorna, esse método retornará o nome de arquivo "completo".

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.