为什么`Paths.get`方法的行为有所不同?

此代码段已打印出\\home\cay\

Path absolute = Paths.get("/","home","cay");
System.out.println(absolute);

但是此打印出myprog\conf\user.properties

Path relative = Paths.get("myprog","conf","user.properties");
System.out.println(relative);

我有两个问题:

  1. 为什么在第一种情况下有两个前导\\
  2. 为什么在第一种情况下尾随\

ps:我在Windows系统上。

wangyin2003 回答:为什么`Paths.get`方法的行为有所不同?

您的第一个路径被解释为DatePicker,没有对象名称。

它是怎么发生的? 深入实施,我们可以找到以下内容:

UNC path

/**
  * Parses the given input as a Windows path.
  * 
  * @param   input - 1st case: '/\home\cay' ; 2nd case: 'myprog\conf\user.properties'
  * @param   requireToNormalize - true for both cases
  */
private static Result parse(String input,boolean requireToNormalize) {
  String root = "";
  WindowsPathType type = null;

  int len = input.length(); // 1st case: len = 10,2nd case: len = 27
  int off = 0;
  if (len > 1) {
    char c0 = input.charAt(0); // 1st case: c0 = '/',2nd case: c0 = 'm'
    char c1 = input.charAt(1); // 1st case: c1 = '\',2nd case: c1 = 'y'
    int next = 2;
    if (isSlash(c0) && isSlash(c1)) // this condition is true ONLY for 1st case
    {
       type = WindowsPathType.UNC;
       off = nextNonSlash(input,next,len); // 1st case: off = 2
       next = nextSlash(input,off,len);    // 1st case: next = 6
       if (off == next)
         throw new InvalidPathException(input,"UNC path is missing hostname");

       String host = input.substring(off,next); // 1st case: host = home
       off = nextNonSlash(input,len);     // 1st case: off = 7
       next = nextSlash(input,len);        // 1st case: next = 10
       if (off == next)
         throw new InvalidPathException(input,"UNC path is missing sharename");

       root = "\\\\" + host + "\\" + input.substring(off,next) + "\\"; // 1st case: root = \\home\cay\
       off = next; // 1st case: off = next = 10
    } else {
      if (isLetter(c0) && c1 == ':') { // this condition is false for 2nd case
        ...
      }
    }
 }
 if (off == 0) { // 1st case: off = 10,2nd case: off = 0
    if (len > 0 && isSlash(input.charAt(0))) { // 2nd case: false
      type = WindowsPathType.DIRECTORY_RELATIVE;
      root = "\\";
    } else {
       type = WindowsPathType.RELATIVE;
    }
  }

  if (requireToNormalize) { // true for both cases
    StringBuilder sb = new StringBuilder(input.length());
    sb.append(root);
    /* 
      1st case: type = UNC,root = '\\home\cay\',off = 10,normalize(...) = '\\home\cay\'
      2nd case: type = RELATIVE,root = '',off = 0,normalize(...) = 'myprog\conf\user.properties'
     */
     return new Result(type,root,normalize(sb,input,off));
   } else {
     ...
   }
}

private static final boolean isSlash(char c) {
  return (c == '\\') || (c == '/');
}

还有sun.nio.fs.WindowsPathParser

因此,对于第一种情况,您将具有 UNC 路径类型,对于第二种情况,您将具有 RELATIVE 路径类型。

如果尝试运行以下代码段,结果将略有不同(由于将出现 object-name ,因此没有最终的\):

Path uncPath = Paths.get("/","my-host","share","obj");
System.out.println(uncPath); //  \\my-host\share\obj

如果您尝试运行以下代码段:

Path uncPath = Paths.get("/","my-host");

您将得到:

java.nio.file.InvalidPathException: UNC path is missing sharename: /\my-host
    at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:118)
    at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
    at sun.nio.fs.WindowsPath.parse(WindowsPath.java:94)
    at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:255)
    at java.nio.file.Paths.get(Paths.java:84)

因为根据sun.nio.fs.WindowsPathType

  

例如,在用于访问SMB共享中文件和目录的UNC路径中,对象名称可以是文件或目录的名称。 主机名共享名对象名被称为“路径名组件”或“路径组件”。 有效的UNC路径由两个或多个路径组成。

,

这是javadoc:

https://docs.oracle.com/javase/8/docs/api/java/nio/file/Paths.html

该实现依赖于系统,因为:

  

通过调用默认FileSystem的getPath方法获得路径。

您似乎在Windows上,并且--entrypoint=tail -f /dev/null已转换为/

我现在在Linux计算机上测试了您的代码:

\\

当我执行上述代码时,它会打印Path absolute = Paths.get("/","home","cay"); System.out.println(absolute); 。 这证明该实现实际上是依赖于系统的。

更新

已删除关于尾部斜杠错误的部分。现在,我进行了更深入的研究,@ SternK的帖子得到了更新,这是完全正确的。

这里是我的补充内容

如@SternK的帖子所示,如果第一个字符是斜杠(在Windows上),则该路径被认为是类型/home/cay,然后该斜杠将被WindowsPathType.UNC替换。 UNC路径至少包含2个级别,而第一个级别代表\\,第二个级别代表host,例如, share)。由于\\hostname\sharename\中没有对象名称(或与此相关的文件路径),因此添加了斜杠,因此斜杠变为\\home\cay。如果您使用\\home\cay\进行尝试,则应该得到/home/cay/file1

希望这会有所帮助!

本文链接:https://www.f2er.com/3152920.html

大家都在问