GetCanonicalPath和toRealPath之间的差异

2022-05-26 00:00:00 java nio
是否存在File.getCanonicalPath()和File.toPath().toRealPath()会产生不同结果的情况? 他们似乎都做了非常相似的事情,但文档从来没有明确表示他们应该做同样的事情。 在边界案例中,我是否倾向于使用其中一种方法? 那么File.getAbsoltePath()和Path.toAbsoltePath()又如何呢--它们应该以相同的方式工作吗?


解决方案

结论:

  • getAbsolutePathgetPath从不失败,因为它们不进行验证
  • getCanonicalPathURL中的驱动器号无效或与当前文件夹不同时得出无效结果
  • toPath().toRealPath()正在检查有效性,但该文件需要存在,并且还可以跟随或不跟随符号链接
  • 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:tarGetu0000Suffix", "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:homeaiserworkestfs	arGet..Target)
F-CAN:     Success(D:homeaiserworkestfs	arget)
P-TO:      Success(d:tarGet..Target)
P-ABS:     Success(D:homeaiserworkestfs	arGet..Target)
P-NOR:     Success(d:Target)
P-NOR-ABS: Success(D:homeaiserworkestfsTarget)
P-ABS-NOR: Success(D:homeaiserworkestfsTarget)
P-REAL:    Success(D:homeaiserworkestfs	arget)

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:homeaiserworkestfs	arGet..Target...)
F-CAN:     Success(D:homeaiserworkestfs)
P-TO:      Success(d:tarGet..Target...)
P-ABS:     Success(D:homeaiserworkestfs	arGet..Target...)
P-NOR:     Success(d:)
P-NOR-ABS: Success(D:homeaiserworkestfs)
P-ABS-NOR: Success(D:homeaiserworkestfs)
P-REAL:    Success(D:homeaiserworkestfs)

Use:  d:tarGet
on-existent....Target... -> Relative path contains non-existent file
F-GET:     Success(d:tarGet
on-existent....Target...)
F-ABS:     Success(d:homeaiserworkestfs	arGet
on-existent....Target...)
F-CAN:     Success(D:homeaiserworkestfs)
P-TO:      Success(d:tarGet
on-existent....Target...)
P-ABS:     Success(D:homeaiserworkestfs	arGet
on-existent....Target...)
P-NOR:     Success(d:)
P-NOR-ABS: Success(D:homeaiserworkestfs)
P-ABS-NOR: Success(D:homeaiserworkestfs)
P-REAL:    Success(D:homeaiserworkestfs)

Use:  d:target\file -> Double slash
F-GET:     Success(d:targetfile)
F-ABS:     Success(d:homeaiserworkestfs	argetfile)
F-CAN:     Success(D:homeaiserworkestfs	argetfile)
P-TO:      Success(d:targetfile)
P-ABS:     Success(D:homeaiserworkestfs	argetfile)
P-NOR:     Success(d:targetfile)
P-NOR-ABS: Success(D:homeaiserworkestfs	argetfile)
P-ABS-NOR: Success(D:homeaiserworkestfs	argetfile)
P-REAL:    Failure(java.nio.file.NoSuchFileException: D:homeaiserworkestfs	argetfile)

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:	arGet..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:	arGet..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:homeaiserworkestfsza:tarGet..Target...)
F-CAN:     Success(D:homeaiserworkestfs)
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:homeaiserworkestfs	arGet|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)

相关文章