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

在Java中getPath()getAbsolutePath()getCanonicalPath()有什么getCanonicalPath()

我什么时候使用每一个?

考虑这些文件名:

C:\temp\file.txt – 这是一个path,一个绝对path和一个规范path。

.\file.txt – 这是一个path。 这既不是一条绝对的道路,也不是一条规范的道路。

C:\temp\myapp\bin\..\\..\file.txt – 这是一个path和一个绝对path。 这不是一个规范的path。

规范的道路永远是一条绝对的道路。

从path转换到规范path使其成为绝对(通常在当前工作目录上,例如./file.txt变为c:/temp/file.txt )。 文件的规范path只是“净化”path,删除和解决像..\和parsing符号链接(在unixes)。

还要注意下面的例子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()); 

虽然两条path都指向相同的位置,但输出将会非常不同:

 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对象的path,这个对象可能是也可能不是相对的; getAbsolutePath()为您提供文件的绝对path; 和getCanonicalPath()为您提供文件的唯一绝对path。 请注意,有相当多的绝对path指向同一个文件,但只有一个规范path。

何时使用每个? 取决于你想完成什么,但是如果你想看看两个Files是否指向磁盘上的同一个文件,你可以比较它们的规范path。 只是一个例子。

简而言之:

  • getPath()获取File对象构造的pathstring,它可能是相对当前目录。
  • getAbsolutePath()在相对于当前目录parsing之后获取pathstring,如果它是相对的,则得到完全限定的path。
  • getCanonicalPath()在根据当前目录parsing任何相对path之后获取pathstring,并删除任何相对path( ... ),以及任何文件系统链接,以返回文件系统认为引用文件系统的规范方法的path它指向的对象。

而且,每个文件都有一个等价的文件,它返回相应的File对象。

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

 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()将根据执行位置或驱动器parsingpath。 所以如果从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()是依赖于系统的。 它将parsingpath所代表的独特位置。 所以,如果你在path中有任何“。”,他们通常会被删除。

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

最让你头痛的是File类试图代表Sun称之为“层级path名”(基本上是“c:/foo.txt”或/ usr / muggins“)的path。就是为什么用path创build文件的原因,你所描述的操作都是这个“path名”上的操作。

  • getPath()获取文件的创buildpath( ../foo.txt
  • getAbsolutePath()获取文件的创buildpath,但包含有关当前目录的信息( /usr/bobstuff/../foo.txt
  • getCanonicalPath() 尝试获取文件绝对path的唯一表示。 这消除了“..”和“。”之间的间接性。 引用( /usr/foo.txt )。

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

我发现我很less需要使用getCanonicalPath()但是,如果在Windows上为DOS 8.3格式的文件(例如java.io.tmpdir系统属性返回getCanonicalPath()指定了文件,则此方法将返回“完整”文件名。