在Java中,getPath()
、getAbsolutePath()
和getCanonicalPath()
有什么区别?
我该何时使用它们?
在Java中,getPath()
、getAbsolutePath()
和getCanonicalPath()
有什么区别?
我该何时使用它们?
考虑以下文件名:
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
可能是一个软链接。我不知道文件系统是否可以区分对文件的硬链接。 - Lawrence DolgetAbsolutePath()
而不是 getCanonicalPath()
。这甚至看起来更好,因为规范化的路径自动解析那些 ../
部分。 - ScadgegetCanonicalPath
抛出 IOException
而 getAbsolutePath
不会抛出异常。 - Abandoned Cart我发现最好的方法是尝试一下,这样可以更好地理解:
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()
根据文件对象提供路径,该路径可能是相对路径,也可能不是; getAbsolutePath()
为您提供了文件的绝对路径;getCanonicalPath()
为您提供了文件的唯一绝对路径。请注意,有大量指向同一文件的绝对路径,但只有一条规范路径。
何时使用每个方法?这取决于您要完成的任务,但是如果您想查看两个 Files
是否指向磁盘上的同一文件,可以比较它们的规范路径,这只是其中一个例子。
getPath()
获取 File
对象构造时的路径字符串,该路径可能是相对于当前目录的。getAbsolutePath()
获取在解析相对路径后与当前目录合并的完全限定路径字符串。getCanonicalPath()
获取解析任何相对路径并删除任何相对路径 (.
和 ..
) 以及任何文件系统链接后的路径字符串,返回文件系统认为引用其指向的文件系统对象的规范方式。此外,每个方法都有一个返回相应 File
对象的等效方法。
请注意,我个人认为 Java 实现的“绝对”路径有误; 它实际上应该删除绝对路径中的任何相对路径元素,而规范形式应删除路径中的任何文件系统链接或连接点。
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()特别有用,可以检查两个文件是否相同。
- Asif Mushtaq理解的重点是,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
系统属性返回的文件,则此方法将返回“完整”文件名。
Path.toAbsolutePath().normalize()
,它是规范化路径和绝对路径之间的一个很好的折中方案。 - eckes