在Java中,getPath(), getAbsolutePath()和getCanonicalPath()之间有什么区别?

在Java中getPath()getAbsolutePath()getCanonicalPath()之间有什么区别?

我什么时候使用它们?

410907 次浏览

简而言之:

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

此外,每个对象都有一个文件等效物,返回相应的File对象。

注意,在IMO中,Java实现了一个“绝对”;路径错了;它实际上应该删除绝对路径中的任何相对路径元素。然后,规范形式将删除路径中的任何FS链接或连接。

考虑这些文件名:

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

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

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

规范路径总是绝对路径。

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

还要注意下面使用nio的示例。道路:

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

我所发现的对这些事情有感觉的最好方法就是去尝试:

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是否指向磁盘上的同一个文件,则可以比较它们的规范路径。举个例子。

您需要了解的一件大事是,File类试图表示Sun喜欢称之为“分层路径名”的视图(基本上是像c:/foo.txt/usr/muggins这样的路径)。这就是为什么要根据路径来创建文件。您描述的操作都是在这个“路径名”上的操作。

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

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

getPath()返回用于创建File对象的路径。这个返回值不会基于它运行的位置而改变(下面的结果是针对窗口的,分隔符在其他地方明显不同)

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(),但是,如果给定一个文件的文件名是在Windows上的DOS 8.3格式,例如java.io.tmpdir系统属性返回,那么这个方法将返回“完整”的文件名。