Java中的getPath(),getAbsolutePath()和getCanonicalPath()有什么区别?


583

什么之间的区别getPath()getAbsolutePath()以及getCanonicalPath()在Java中?

我什么时候使用每个?


不要忘记Path.toAbsolutePath().normalize()哪一个是介于规范(真实)路径和绝对路径之间的良好中间地带。
eckes

Answers:


625

考虑以下文件名:

C:\temp\file.txt -这是一条路径,一条绝对路径和一条规范路径。

.\file.txt-这是一条路。它既不是绝对路径也不是规范路径。

C:\temp\myapp\bin\..\\..\file.txt-这是一条路径,也是一条绝对路径。这不是一条规范的道路。

规范路径始终是绝对路径。

从路径转换为规范路径使其成为绝对路径(通常添加到当前工作目录,因此例如./file.txt成为c:/temp/file.txt)。文件的规范路径仅“净化”路径,删除..\并解决符号链接之类的问题并解决(在Unix上)符号链接。

还要注意以下带有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());

虽然两个路径都指向相同的位置,但是输出将大不相同:

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

11
FWIW,不是一个给定C:\temp\file.txt的规范路径-临时目录可能是文件系统软链接或硬链接(NTFS中的连接),而file.txt可能是软链接。我不知道文件系统是否可以区分文件的硬链接。
劳伦斯·多尔

1
path并不真正考虑那些问题或任何组件的存在,仅考虑它的语法。
escape-llc

确实,规范路径(与规范化路径不同)确实命中了文件系统。
eckes

1
基本上,我看不出为什么应该使用getAbsolutePath()而不是的原因getCanonicalPath()。甚至看起来更好,因为规范的../部分会自动解析这些部分。
Scadge '18

不要忘了,getCanonicalPath抛出IOException虽然getAbsolutePath没有,如果这是一个考虑因素。
被遗弃的购物车

129

我发现对这种事情有感觉的最好方法是尝试一下:

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

您的输出将类似于:

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

因此,getPath()为您提供基于File对象的路径,该路径可能是相对的,也可能不是相对的;getAbsolutePath()为您提供文件的绝对路径;并getCanonicalPath()为您提供文件的唯一绝对路径。请注意,有大量指向同一文件的绝对路径,但只有一个规范路径。

什么时候使用每个?取决于您要完成的工作,但是如果要查看两个Files文件是否指向磁盘上的同一文件,则可以比较它们的规范路径。只是一个例子。


7
Java误将其“绝对”路径实现错误是有争议的。它确实应该删除绝对路径中的所有相对路径元素。然后,规范形式将删除路径中的所有FS链接或结点。
劳伦斯·多尔2014年

but if you were trying to see if two Files are pointing at the same file on disk怎么样?请举个例子吗?
Asif Mushtaq

@UnKnown:您将使用规范路径。
劳伦斯·多尔

67

简而言之:

  • getPath()获取File构造对象的路径字符串,它可能是相对当前目录。
  • getAbsolutePath() 在相对于当前目录(如果是相对目录)进行解析之后,获取路径字符串,从而得到完全限定的路径。
  • getCanonicalPath()在针对当前目录解析任何相对路径之后,获取路径字符串,并删除所有相对路径(...),并且任何文件系统链接都返回一个路径,文件系统认为该路径是引用它指向的文件系统对象的规范方法。

同样,每个File对象都有一个File等效项,它返回相应的对象。


36

getPath()返回用于创建File对象的路径。此返回值不会根据其运行位置进行更改(以下结果适用于Windows,分隔符在其他地方明显不同)

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()将根据执行位置或驱动器解析路径。因此,如果从运行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()与系统有关。它将解析路径表示的唯一位置。因此,如果路径中有任何“。”,通常将其删除。

至于何时使用它们。这取决于您要实现的目标。getPath()对于可移植性很有用。getAbsolutePath()查找文件系统位置getCanonicalPath()非常有用,对于检查两个文件是否相同特别有用。


你能举个例子吗?getCanonicalPath() is particularly useful to check if two files are the same.
Asif Mushtaq

20

直截了当的是,File该类试图代表Sun所称的“分层路径名”(基本上是类似c:/foo.txtor 的路径/usr/muggins)的视图。这就是为什么要根据路径创建文件的原因。您描述的操作都是针对此“路径名”的所有操作。

  • getPath()获取使用(../foo.txt)创建文件的路径
  • getAbsolutePath()获取创建文件的路径,但如果路径是相对的(/usr/bobstuff/../foo.txt),则包含有关当前目录的信息
  • getCanonicalPath() 尝试获取文件绝对路径的唯一表示形式。这消除了“ ..”和“。”的间接访问。参考(/usr/foo.txt)。

请注意,我说的是尝试 -在形成规范路径时,VM可以抛出IOException。这通常是因为它正在执行某些文件系统操作,而其中任何一个操作都可能失败。


3

我发现我很少需要使用,getCanonicalPath()但是,如果给定的文件的文件名在Windows上为DOS 8.3格式,例如java.io.tmpdirSystem属性返回,则此方法将返回“完整”文件名。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.