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).
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;publicclassPathTesting{publicstaticvoid main(String[] args){File f =newFile("test/.././file.txt");System.out.println(f.getPath());System.out.println(f.getAbsolutePath());try{System.out.println(f.getCanonicalPath());}catch(Exception e){}}}
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.
É 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 .
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 =newFile("/some/path");String path = f1.getPath();// will return "\some\path"File dir =newFile("/basedir");File f2 =newFile(dir,"/some/path");
path = f2.getPath();// will return "\basedir\some\path"File f3 =newFile("./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.
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".
Path.toAbsolutePath().normalize()
qual é um bom meio termo entre o caminho canônico (real) e o caminho absoluto sozinho.Respostas:
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.txt
torna-sec:/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:
Enquanto os dois caminhos se referem ao mesmo local, a saída será bem diferente:
fonte
C:\temp\file.txt
canô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.getAbsolutePath()
vez degetCanonicalPath()
. Até parece melhor porque o canônico resolve essas../
partes automaticamente .getCanonicalPath
joga umIOException
tempogetAbsolutePath
não, se isso é uma consideração.A melhor maneira que encontrei para experimentar coisas assim é experimentá-las:
Sua saída será algo como:
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
Files
estão apontando para o mesmo arquivo no disco, você pode comparar seus caminhos canônicos. Apenas um exemplo.fonte
but if you were trying to see if two Files are pointing at the same file on disk
Quão? exemplo por favor?Em resumo:
getPath()
obtém a cadeia de caminho com a qual oFile
objeto 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
File
objeto correspondente .fonte
getPath()
retorna o caminho usado para criar oFile
objeto. 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)getAbsolutePath()
resolverá o caminho com base no local de execução ou na unidade. Portanto, se executado a partir dec:\test
: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 egetCanonicalPath()
é particularmente útil para verificar se dois arquivos são iguais.fonte
getCanonicalPath() is particularly useful to check if two files are the same.
O mais importante é que a
File
classe tenta representar uma visão do que a Sun gosta de chamar de "nomes de caminhos hierárquicos" (basicamente um caminho comoc:/foo.txt
ou/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.fonte
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 ajava.io.tmpdir
propriedade System retorna, esse método retornará o nome de arquivo "completo".fonte