Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paths.get on Windows

Tags:

java

Consider a method starting like this:

private void writeFile(String dir, String name) {
    Path path = Paths.get(dir, name);
    // create & write to file, etc...

Now the caller of this method might want to create the file in a specified directory, such as one of the following:

  1. "C:\path\to\dir" absolute path on specified drive
  2. "path\to\dir" relative path
  3. "\path\to\dir" absolute path on current drive
  4. "C:\" root directory of specified drive
  5. "\" root directory of current drive

The problem is that the last one (i.e. Paths.get("\\", "x.txt")) gives the following error:

Exception in thread "main" java.nio.file.InvalidPathException: UNC path is missing sharename: \\x.txt

Would this be considered a bug? If not, how would you create a file in the root of the current drive in Windows?

like image 356
Klitos Kyriacou Avatar asked Oct 19 '22 22:10

Klitos Kyriacou


1 Answers

Yeah, I'd consider that a bug.

If you look at the code for WindowsFileSystem.getPath(String paramString, String... paramVarArgs), you'll find this code (jdk1.8.0_51, source of WindowsFileSystem not included, so this is from disassembler):

public final Path getPath(String paramString, String... paramVarArgs)
{
  String str1;
  if (paramVarArgs.length == 0) {
    str1 = paramString;
  } else {
    StringBuilder localStringBuilder = new StringBuilder();
    localStringBuilder.append(paramString);
    for (String str2 : paramVarArgs) {
      if (str2.length() > 0) {
        if (localStringBuilder.length() > 0)
          localStringBuilder.append('\\');
        localStringBuilder.append(str2);
      }
    }
    str1 = localStringBuilder.toString();
  }
  return WindowsPath.parse(this, str1);
}

The code adds \ between elements, even if preceding element already ends with a \, relying on a\\b to be compacted to a\b in the WindowsPath.parse() method.

So, get("\\", "x.txt") becomes \\x.txt, and two \ at the beginning is a UNC path, so parse() fails.

Suggestion, if you want to file a bug. Change code to:

      if (str2.length() > 0) {
        if (localStringBuilder.length() > 0) {
          char c = localStringBuilder.charAt(localStringBuilder.length() - 1);
          if (c != '\\' && c != '/')
            localStringBuilder.append('\\');
        }
        localStringBuilder.append(str2);
      }
like image 162
Andreas Avatar answered Oct 21 '22 17:10

Andreas