jjzjj

java - getCanonicalPath 和 toRealPath 之间的区别

coder 2024-03-11 原文

是否存在 File.getCanonicalPath() 和 File.toPath().toRealPath() 会产生不同结果的情况? 他们似乎都做了相当相似的事情,但文档从未真正说明他们应该做同样的事情。 是否存在我更喜欢一种方法而不是另一种方法的边界情况? File.getAbsolutePath() 与 Path.toAbsolutePath() 又如何 - 它们应该以相同的方式工作吗?

最佳答案

结论:

  • getAbsolutePathgetPath 永远不会失败,因为它们不进行验证
  • getCanonicalPath 当来自 url 的盘符无效或与当前文件夹不同时得到无效结果
  • 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/

有关java - getCanonicalPath 和 toRealPath 之间的区别的更多相关文章

  1. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  2. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  3. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  4. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  5. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  6. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  7. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  8. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  9. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  10. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

随机推荐