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

What's the difference between getPath(), getAbsolutePath(), and getCanonicalPath() in Java?

在Java中EDCOX1 0,EDOCX1,1,EDCX1 2的区别是什么?

我什么时候使用每一个呢?


考虑这些文件名:

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

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

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

规范路径总是绝对路径。

从路径转换为规范路径使其成为绝对路径(通常附加在当前工作目录上,例如,./file.txt变为c:/temp/file.txt)。文件的规范路径只是"净化"路径,删除和解析诸如..\之类的东西,并解析符号链接(在unix上)。

还请注意以下NIO.Paths示例:

1
2
3
4
5
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());

虽然这两条路径都指向同一个位置,但输出将完全不同:

1
2
C:\Windows
C:\Windows\System32\drivers


我找到的最好的方法就是尝试一下:

1
2
3
4
5
6
7
8
9
10
11
12
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) {}
    }
}

您的输出将类似于:

1
2
3
test\..\.\file.txt
C:\projects\sandbox\trunk\test\..\.\file.txt
C:\projects\sandbox\trunk\file.txt

因此,getPath()给出了基于文件对象的路径,它可能是相对的,也可能不是相对的;getAbsolutePath()给出了文件的绝对路径;getCanonicalPath()给出了文件的唯一绝对路径。请注意,有大量绝对路径指向同一个文件,但只有一个规范路径。

何时使用?取决于您试图完成的任务,但是如果您试图查看两个Files是否指向磁盘上的同一个文件,则可以比较它们的规范路径。只是一个例子。


简而言之:

  • getPath()获取File对象所用的路径字符串,它可能是相对当前目录。
  • getAbsolutePath()根据当前目录(如果是相对目录)解析后得到路径字符串,从而得到完全限定的路径。
  • getCanonicalPath()在对当前目录解析任何相对路径后获取路径字符串,并删除任何相对路径(...,以及任何文件系统链接以返回文件系统认为引用其所指向的文件系统对象的规范方式的路径。

此外,每种方法都有一个文件等价物,返回对应的File对象。


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

1
2
3
4
5
6
7
8
9
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运行:

1
2
3
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()依赖于系统。它将解析路径表示的唯一位置。因此,如果路径中有任何"."s,它们通常都会被删除。

关于何时使用它们。这取决于你想要达到的目标。getPath()对于可移植性很有用。getAbsolutePath()用于查找文件系统位置,getCanonicalPath()尤其用于检查两个文件是否相同。


让你头脑清醒的一件大事是,File类试图代表一种观点,即sun喜欢称之为"分层路径名"(基本上是一种类似c:/foo.txt/usr/muggins的路径)。这就是为什么要根据路径创建文件。您描述的操作都是对这个"路径名"的操作。

  • getPath()获取创建文件的路径(../foo.txt)
  • getAbsolutePath()获取创建文件的路径,但如果路径是相对的,则包含有关当前目录的信息(/usr/bobstuff/../foo.txt)
  • getCanonicalPath()试图获取文件绝对路径的唯一表示。这就消除了".."和"."引用的间接性(/usr/foo.txt)。

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


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