【发布时间】:2010-11-09 02:47:18
【问题描述】:
getPath()、getAbsolutePath() 和 getCanonicalPath() 在 Java 中的区别是什么?
我什么时候使用它们?
【问题讨论】:
-
不要忘记
Path.toAbsolutePath().normalize(),这是一个介于规范(真实)路径和绝对路径之间的良好中间地带。
标签: java
getPath()、getAbsolutePath() 和 getCanonicalPath() 在 Java 中的区别是什么?
我什么时候使用它们?
【问题讨论】:
Path.toAbsolutePath().normalize(),这是一个介于规范(真实)路径和绝对路径之间的良好中间地带。
标签: java
简而言之:
getPath() 获取构造File 对象的路径字符串,它可能是相对当前目录。getAbsolutePath() 在根据当前目录解析后获取路径字符串(如果它是相对的),从而产生完全限定的路径。getCanonicalPath() 在针对当前目录解析任何相对路径后获取路径字符串,并删除任何相对路径(. 和 ..),以及任何文件系统链接以返回文件系统认为规范引用的路径它指向的文件系统对象。此外,它们中的每一个都有一个 File 等效项,它返回相应的 File 对象。
请注意,IMO,Java 错误地实现了“绝对”路径;它确实应该删除绝对路径中的任何相对路径元素。然后,规范形式将删除路径中的任何 FS 链接或交汇点。
【讨论】:
最重要的是File 类试图代表Sun 喜欢称之为“分层路径名”的视图(基本上是c:/foo.txt 或/usr/muggins 之类的路径)。这就是您根据路径创建文件的原因。您描述的操作都是对这个“路径名”的操作。
getPath() 获取创建文件的路径 (../foo.txt)getAbsolutePath() 获取创建文件的路径,但如果路径是相对的,则包含有关当前目录的信息 (/usr/bobstuff/../foo.txt)getCanonicalPath() 尝试获取文件绝对路径的唯一表示。这消除了“..”和“.”的间接性。参考资料 (/usr/foo.txt)。注意我说的是尝试 - 在形成规范路径时,VM 可以抛出 IOException。这通常是因为它正在执行一些文件系统操作,其中任何一个都可能失败。
【讨论】:
考虑这些文件名:
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
【讨论】:
C:\temp\file.txt 并不是一个规范路径——临时目录可能是文件系统软链接或硬链接(NTFS 中的一个结点),而 file.txt 可能是一个软链接。不知道文件系统能不能区分文件的硬链接。
getAbsolutePath() 而不是getCanonicalPath()。它甚至看起来更好,因为规范的自动解析那些../ 部分。
getCanonicalPath 会抛出一个IOException 而getAbsolutePath 不会,如果这是一个考虑因素的话。
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.
我发现我很少需要使用getCanonicalPath(),但是,如果在 Windows 上给定一个文件名是 DOS 8.3 格式的文件,例如 java.io.tmpdir 系统属性返回,那么这个方法将返回“完整" 文件名。
【讨论】:
我发现了解此类事情的最佳方法是尝试一下:
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 是否指向磁盘上的同一个文件,您可以比较它们的规范路径。只是一个例子。
【讨论】:
but if you were trying to see if two Files are pointing at the same file on disk 怎么样?请举例?