JDK-8190546 : File.toPath() reject directory names with trailing space
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 7u40,8,9
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows
  • CPU: x86_64
  • Submitted: 2017-10-27
  • Updated: 2025-04-10
  • Resolved: 2017-12-10
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
64-bit Windows. Can't be more specific as the error occured on an end-user's machine, but I've also done some testing with 64-bit windows 7 (Microsoft Windows [Version 6.1.7601])



A DESCRIPTION OF THE PROBLEM :
I know this is an old JRE, but the same bug is reported against JDK 1.9.0 b116: https://bugs.openjdk.java.net/browse/JDK-8156657

The bug was closed with the assertion that "this is not allowed on windows", which as far as I can tell has no basis. The Windows UI certainly makes it hard to get into this situation (eg. explorer automatically trims leading/trailing whitespace from file/directory names), but when dealing with network file systems it's certainly possible and Windows itself copes with the trailing space fine.

Well, mostly fine. It's hard/impossible to convince to convince cmd.exe to cd into a dir with trailing spaces, but it can access files/subdirectories within it. eg. I'm in a directory tree which looks like:

    abc \
        def\
            ghi\
            c.txt
        lol

That is, the immediate sub-dir "abc " has a trailing space. From here, the following commands fail with "The system cannot find the path specified.":

* cd abc
* cd "abc "
* cd "%CD%\abc \"

But these commands work fine:

* type "abc \def\c.txt"
* type "abc \lol"
* cd "abc \def\ghi"

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Export a filesystem which includes a directory with trailing/leading whitespace to a windows machine
2. Try to access and normalize paths under that directory

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Normalization succeeds.
ACTUAL -
Normalization failed. The exception in this case looks like this (where I've scrambled the path's alphanumeric content to censor customer data):

 java.nio.file.InvalidPathException: Trailing char < > at index 124: \\ei.uqpe.hhh\Ugehrt\IDPIC\GLZ\EXM_Rezxbl\74_Lvagfbqmoxgy_Iwcyjp\Zogbcrxpczhl Toeuyg Nvpwb\Iaucgvdgmyxb Ykcgfd - EQI VGB BIN \Ofrgeki Rnqp\Zoocjlofds\VUC Oiwbvua Ojyvwffadj\Eio Bzxzyi - KR80 17D\91F_Hqdsxpwalt_Lzpfes.gjs
 	at sun.nio.fs.WindowsPathParser.normalize(Unknown Source)
 	at sun.nio.fs.WindowsPathParser.parse(Unknown Source)
 	at sun.nio.fs.WindowsPathParser.parse(Unknown Source)
 	at sun.nio.fs.WindowsPath.parse(Unknown Source)
 	at sun.nio.fs.WindowsFileSystem.getPath(Unknown Source)
 	at java.io.File.toPath(Unknown Source)

where the File in question was provided by JFileChooser.getSelectedFiles().

REPRODUCIBILITY :
This bug can be reproduced rarely.

---------- BEGIN SOURCE ----------
import java.io.File;
import java.io.FileInputStream;

public class trailing_space {
    public static void main(String[] args) throws Exception {
        /* NOTE: this relies on a pre-existing directory structure like the one in the description existing */
        File dir = new File("abc ");
        File f = new File(dir, "lol");

        /* Dump the contents of "abc \lol" to demonstrate that Windows is not restricting access */
        byte[] buf = new byte[1024];
        try (FileInputStream s = new FileInputStream(f)) {
            int len = s.read(buf);
            System.out.println(new String(buf, 0, len));
        }

        /* Now try to normalise the path -- crashes here */
        System.out.println(f.toPath());
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Avoid using java.io.Path, I guess. Or rename the directory.


Comments
A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk/pull/8788 Date: 2022-05-19 13:11:11 +0000
19-05-2022

There isn't anything new that I can throw in support of allowing JDK to work with such file names. But the old points can perhaps be re-visited. AFAIU, the only reason to explicitly forbid that (see WindowsPathParser.normalize()) was that the parsing is based on Windows documentation like [1]. That documentation says the following: "Do not end a file or directory name with a space or a period. Although the underlying file system may support such names, the Windows shell and user interface does not" Indeed, it's hard or even impossible to create such a file using "normal" windows GUI, but you can still use that GUI to delete such a file. In Java, you can't do either. Working in a cygwin terminal, you can fairly easily create a file name ending with a space. And when you turn to your Java-based IDE to delete it, you get an error from the very basic level of NIO that you can't overrule, which seems to be quite unfortunate. If there's any interest in resolving this - or at least not enough opposition to let it be resolved - I am willing to make the necessary changes and open a PR. References [1] https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions
16-05-2022

Windows file paths are parsed based on the Windows documentation on legacy file names and paths. The rejection of directory names ending with a space is deliberate. I think this bug report is really a request to allow this, maybe because the underlying file system supports or because it is shared with non-Windows hosts.
02-11-2017