Java中的getPath()、getAbsolutePath()和getCanonicalPath()有什么区别?
我什么时候使用它们?
Java中的getPath()、getAbsolutePath()和getCanonicalPath()有什么区别?
我什么时候使用它们?
简而言之:
getPath() gets the path string that the File object was constructed with, and it may be relative current directory. getAbsolutePath() gets the path string after resolving it against the current directory if it's relative, resulting in a fully qualified path. getCanonicalPath() gets the path string after resolving any relative path against current directory, and removes any relative pathing (. and ..), and any file system links to return a path which the file system considers the canonical means to reference the file system object to which it points.
此外,每个对象都有一个返回相应File对象的File等价物。
注意,在我看来,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()为您提供文件的唯一绝对路径。注意,有大量的绝对路径指向同一个文件,但只有一个规范路径。
什么时候使用它们?这取决于您想要完成的任务,但如果您试图查看两个file是否指向磁盘上的同一个文件,则可以比较它们的规范路径。举个例子。
需要注意的是,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系统属性返回,那么这个方法将返回“完整的”文件名。