在某些情况下File.getCanonicalPath()和File.toPath()。toRealPath()会产生不同的结果吗?
他们似乎都做类似的事情,但是文档从来没有说明他们应该做同样的事情。
在边境情况下,我是否会偏爱一种方法?
以及File.getAbsolutePath()与Path.toAbsolutePath()怎么样-它们应该以相同的方式工作吗?

最佳答案

结论:

  • getAbsolutePathgetPath永远不会失败,因为它们不进行验证
  • 当来自URL的驱动器号无效或不同于当前文件夹时,
  • getCanonicalPath达到无效结果
  • toPath().toRealPath()正在检查有效性,但是文件必须存在,并且可以跟随或不跟随符号链接(symbolic link)
  • toPath()足够安全,不需要文件存在。
  • .toPath().toAbsolutePath().normalize()是不需要文件存在的最佳版本

  • 我在Windows中对@John做过类似的测试
      @Test
      public void testCanonical() throws IOException {
        test("d:tarGet\\..\\Target", "File exist and drive letter is on the current one");
        test("d:tarGet\\..\\Target\\.\\..\\", "File exist and drive letter is on the current one, but parent of current drive should exist");
        test("d:tarGet\\non-existent\\..\\..\\Target\\.\\..\\", "Relative path contains non-existent file");
        test("d:target\\\\file", "Double slash");
        test("c:tarGet\\..\\Target\\.", "File doesn't exist and drive letter is on different drive than the current one");
        test("l:tarGet\\..\\Target\\.\\..\\", "Drive letter doesn't exist");
        test("za:tarGet\\..\\Target\\.\\..\\", "Drive letter is double so not valid");
        test("d:tarGet|Suffix", "Path contains invalid chars in windows (|)");
        test("d:tarGet\u0000Suffix", "Path contains invalid chars in both linux and windows (\\0)");
      }
    
      private void test(String filename, String message) throws IOException {
        java.io.File file = new java.io.File(filename);
        System.out.println("Use:  " + filename + " -> " + message);
        System.out.println("F-GET:     " + Try.of(() -> file.getPath()));
        System.out.println("F-ABS:     " + Try.of(() -> file.getAbsolutePath()));
        System.out.println("F-CAN:     " + Try.of(() -> file.getCanonicalPath()));
        System.out.println("P-TO:      " + Try.of(() -> file.toPath()));
        System.out.println("P-ABS:     " + Try.of(() -> file.toPath().toAbsolutePath()));
        System.out.println("P-NOR:     " + Try.of(() -> file.toPath().normalize()));
        System.out.println("P-NOR-ABS: " + Try.of(() -> file.toPath().normalize().toAbsolutePath()));
        System.out.println("P-ABS-NOR: " + Try.of(() -> file.toPath().toAbsolutePath().normalize()));
        System.out.println("P-REAL:    " + Try.of(() -> file.toPath().toRealPath()));
        System.out.println("");
      }
    
    结果是:
    Use:  d:tarGet\..\Target -> File exist and drive letter is on the current one
    F-GET:     Success(d:tarGet\..\Target)
    F-ABS:     Success(d:\home\raiser\work\restfs\tarGet\..\Target)
    F-CAN:     Success(D:\home\raiser\work\restfs\target)
    P-TO:      Success(d:tarGet\..\Target)
    P-ABS:     Success(D:\home\raiser\work\restfs\tarGet\..\Target)
    P-NOR:     Success(d:Target)
    P-NOR-ABS: Success(D:\home\raiser\work\restfs\Target)
    P-ABS-NOR: Success(D:\home\raiser\work\restfs\Target)
    P-REAL:    Success(D:\home\raiser\work\restfs\target)
    
    Use:  d:tarGet\..\Target\.\..\ -> File exist and drive letter is on the current one, but parent of current drive should exist
    F-GET:     Success(d:tarGet\..\Target\.\..)
    F-ABS:     Success(d:\home\raiser\work\restfs\tarGet\..\Target\.\..)
    F-CAN:     Success(D:\home\raiser\work\restfs)
    P-TO:      Success(d:tarGet\..\Target\.\..)
    P-ABS:     Success(D:\home\raiser\work\restfs\tarGet\..\Target\.\..)
    P-NOR:     Success(d:)
    P-NOR-ABS: Success(D:\home\raiser\work\restfs\)
    P-ABS-NOR: Success(D:\home\raiser\work\restfs)
    P-REAL:    Success(D:\home\raiser\work\restfs)
    
    Use:  d:tarGet\non-existent\..\..\Target\.\..\ -> Relative path contains non-existent file
    F-GET:     Success(d:tarGet\non-existent\..\..\Target\.\..)
    F-ABS:     Success(d:\home\raiser\work\restfs\tarGet\non-existent\..\..\Target\.\..)
    F-CAN:     Success(D:\home\raiser\work\restfs)
    P-TO:      Success(d:tarGet\non-existent\..\..\Target\.\..)
    P-ABS:     Success(D:\home\raiser\work\restfs\tarGet\non-existent\..\..\Target\.\..)
    P-NOR:     Success(d:)
    P-NOR-ABS: Success(D:\home\raiser\work\restfs\)
    P-ABS-NOR: Success(D:\home\raiser\work\restfs)
    P-REAL:    Success(D:\home\raiser\work\restfs)
    
    Use:  d:target\\file -> Double slash
    F-GET:     Success(d:target\file)
    F-ABS:     Success(d:\home\raiser\work\restfs\target\file)
    F-CAN:     Success(D:\home\raiser\work\restfs\target\file)
    P-TO:      Success(d:target\file)
    P-ABS:     Success(D:\home\raiser\work\restfs\target\file)
    P-NOR:     Success(d:target\file)
    P-NOR-ABS: Success(D:\home\raiser\work\restfs\target\file)
    P-ABS-NOR: Success(D:\home\raiser\work\restfs\target\file)
    P-REAL:    Failure(java.nio.file.NoSuchFileException: D:\home\raiser\work\restfs\target\file)
    
    Use:  c:tarGet\..\Target\. -> File doesn't exist and drive letter is on different drive than the current one
    F-GET:     Success(c:tarGet\..\Target\.)
    F-ABS:     Success(c:\\tarGet\..\Target\.)
    F-CAN:     Success(C:\Target)
    P-TO:      Success(c:tarGet\..\Target\.)
    P-ABS:     Success(C:\tarGet\..\Target\.)
    P-NOR:     Success(c:Target)
    P-NOR-ABS: Success(C:\Target)
    P-ABS-NOR: Success(C:\Target)
    P-REAL:    Failure(java.nio.file.NoSuchFileException: C:\Target)
    
    Use:  l:tarGet\..\Target\.\..\ -> Drive letter doesn't exist
    F-GET:     Success(l:tarGet\..\Target\.\..)
    F-ABS:     Success(l:\tarGet\..\Target\.\..)
    F-CAN:     Success(L:\)
    P-TO:      Success(l:tarGet\..\Target\.\..)
    P-ABS:     Failure(java.io.IOError: java.io.IOException: Unable to get working directory of drive 'L')
    P-NOR:     Success(l:)
    P-NOR-ABS: Failure(java.io.IOError: java.io.IOException: Unable to get working directory of drive 'L')
    P-ABS-NOR: Failure(java.io.IOError: java.io.IOException: Unable to get working directory of drive 'L')
    P-REAL:    Failure(java.io.IOException: Unable to get working directory of drive 'L')
    
    Use:  za:tarGet\..\Target\.\..\ -> Drive letter is double so not valid
    F-GET:     Success(za:tarGet\..\Target\.\..)
    F-ABS:     Success(D:\home\raiser\work\restfs\za:tarGet\..\Target\.\..)
    F-CAN:     Success(D:\home\raiser\work\restfs)
    P-TO:      Failure(java.nio.file.InvalidPathException: Illegal char <:> at index 2: za:tarGet\..\Target\.\..)
    P-ABS:     Failure(java.nio.file.InvalidPathException: Illegal char <:> at index 2: za:tarGet\..\Target\.\..)
    P-NOR:     Failure(java.nio.file.InvalidPathException: Illegal char <:> at index 2: za:tarGet\..\Target\.\..)
    P-NOR-ABS: Failure(java.nio.file.InvalidPathException: Illegal char <:> at index 2: za:tarGet\..\Target\.\..)
    P-ABS-NOR: Failure(java.nio.file.InvalidPathException: Illegal char <:> at index 2: za:tarGet\..\Target\.\..)
    P-REAL:    Failure(java.nio.file.InvalidPathException: Illegal char <:> at index 2: za:tarGet\..\Target\.\..)
    
    Use:  d:tarGet|Suffix -> Path contains invalid chars in windows (|)
    F-GET:     Success(d:tarGet|Suffix)
    F-ABS:     Success(d:\home\raiser\work\restfs\tarGet|Suffix)
    F-CAN:     Failure(java.io.IOException: The filename, directory name, or volume label syntax is incorrect)
    P-TO:      Failure(java.nio.file.InvalidPathException: Illegal char <|> at index 8: d:tarGet|Suffix)
    P-ABS:     Failure(java.nio.file.InvalidPathException: Illegal char <|> at index 8: d:tarGet|Suffix)
    P-NOR:     Failure(java.nio.file.InvalidPathException: Illegal char <|> at index 8: d:tarGet|Suffix)
    P-NOR-ABS: Failure(java.nio.file.InvalidPathException: Illegal char <|> at index 8: d:tarGet|Suffix)
    P-ABS-NOR: Failure(java.nio.file.InvalidPathException: Illegal char <|> at index 8: d:tarGet|Suffix)
    P-REAL:    Failure(java.nio.file.InvalidPathException: Illegal char <|> at index 8: d:tarGet|Suffix)
    

    关于java - getCanonicalPath和toRealPath之间的区别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30920623/

    10-12 01:22