Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validate a file name on Windows

public static boolean isValidName(String text)
{
    Pattern pattern = Pattern.compile("^[^/./\\:*?\"<>|]+$");
    Matcher matcher = pattern.matcher(text);
    boolean isMatch = matcher.matches();
    return isMatch;
}

Does this method guarantee a valid filename on Windows?

like image 358
Eng.Fouad Avatar asked Jul 18 '11 07:07

Eng.Fouad


People also ask

How do I make a file name valid?

Don't start or end your filename with a space, period, hyphen, or underline. Keep your filenames to a reasonable length and be sure they are under 31 characters. Most operating systems are case sensitive; always use lowercase. Avoid using spaces and underscores; use a hyphen instead.

Why is it saying my file name is not valid?

'FileName is not valid': while creating and saving, or opening an Excel file such error may mean one of the following reason: Path of file including file name may exceed 218 number of characters limit. The file name may be incorrect. The path may not be appropriate.


4 Answers

Given the requirements specified in the previously cited MSDN documentation, the following regex should do a pretty good job:

public static boolean isValidName(String text)
{
    Pattern pattern = Pattern.compile(
        "# Match a valid Windows filename (unspecified file system).          \n" +
        "^                                # Anchor to start of string.        \n" +
        "(?!                              # Assert filename is not: CON, PRN, \n" +
        "  (?:                            # AUX, NUL, COM1, COM2, COM3, COM4, \n" +
        "    CON|PRN|AUX|NUL|             # COM5, COM6, COM7, COM8, COM9,     \n" +
        "    COM[1-9]|LPT[1-9]            # LPT1, LPT2, LPT3, LPT4, LPT5,     \n" +
        "  )                              # LPT6, LPT7, LPT8, and LPT9...     \n" +
        "  (?:\\.[^.]*)?                  # followed by optional extension    \n" +
        "  $                              # and end of string                 \n" +
        ")                                # End negative lookahead assertion. \n" +
        "[^<>:\"/\\\\|?*\\x00-\\x1F]*     # Zero or more valid filename chars.\n" +
        "[^<>:\"/\\\\|?*\\x00-\\x1F\\ .]  # Last char is not a space or dot.  \n" +
        "$                                # Anchor to end of string.            ", 
        Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.COMMENTS);
    Matcher matcher = pattern.matcher(text);
    boolean isMatch = matcher.matches();
    return isMatch;
}

Note that this regex does not impose any limit on the length of the filename, but a real filename may be limited to 260 or 32767 chars depending on the platform.

like image 93
ridgerunner Avatar answered Oct 13 '22 13:10

ridgerunner


Not enough,in Windows and DOS, some words might also be reserved and can not be used as filenames.

CON, PRN, AUX, CLOCK$, NUL
COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9
LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.

See~

http://en.wikipedia.org/wiki/Filename


Edit:

Windows usually limits file names to 260 characters. But the file name must actually be shorter than that, since the complete path (such as C:\Program Files\filename.txt) is included in this character count.

This is why you might occasionally encounter an error when copying a file with a very long file name to a location that has a longer path than its current location.

like image 43
Monday Avatar answered Oct 13 '22 13:10

Monday


Well, I think the following method would guarantee a valid file name:

public static boolean isValidName(String text)
{
    try
    {
        File file = new File(text);
        file.createNewFile();
        if(file.exists()) file.delete();
        return true;
    }
    catch(Exception ex){}
    return false;
}

What do you think?

like image 30
Eng.Fouad Avatar answered Oct 13 '22 13:10

Eng.Fouad


A method that guarantees, generally, that a Windows filename is valid -- that it would be legal to create a file of that name -- would be impossible to implement.

It is relatively straightforward to guarantee that a Windows filename is invalid. Some of the other regexes attempt to do this. However, the original question requests a stronger assertion: a method that guarantees the filename is valid on Windows.

The MSDN reference cited in other answers indicates that a Windows filename cannot contain "Any other character that the target file system does not allow". For instance, a file containing NUL would be invalid on some file systems, as would extended Unicode characters on some older file systems. Thus, a file called ☃.txt would be valid in some cases, but not others. So whether a hypothetical isValidName(\"☃\") would return true is dependent on the underlying file system.

Suppose, however, such a function is conservative and requires the filename consist of printable ASCII characters. All modern versions of Windows natively support NTFS, FAT32, and FAT16 file formats, which accept Unicode filenames. But drivers for arbitrary filesystems can be installed, and one is free to create a filesystem that doesn't allow, for instance, the letter 'n'. Thus, not even a simple file like "snowman.txt" can be "guaranteed" to be valid.

But even with extreme cases aside, there are other complications. For instance, a file named "$LogFile" cannot exist in the root of a NTFS volume, but can exist elsewhere on the volume. Thus, without knowing the directory, we cannot know if "$LogFile" is a valid name. But even "C:\data\$LogFile" might be invalid if, say, "c:\data\" is a symbolic link to another NTFS volume root. (Similarly, "D:\$LogFile" can be valid if D: is an alias to a subdirectory of an NTFS volume.)

There are even more complications. Alternate data streams on files, for instance, are legal on NTFS volumes, so "snowman.txt:☃" may be valid. All three major Windows file systems have path length restructions, so the validity of the file name is also function of the path. But the length of the physical path might not even be available to isValidName if the path is a virtual alias, mapped network drive, or symbolic link rather than a physical path on the volume.

Some others have suggested an alternative: create a file by the proposed name and then delete it, returning true if and only if the creation succeeds. This approach has several practical and theoretical problems. One, as indicated earlier, is that the validity is a function both of the filename and the path, so the validity of c:\test\☃.txt might differ from the validity of c:\test2\☃.txt. Also, the function would fail to write the file for any number of reasons not related to the validity of the file, such as not having write permission to the directory. A third flaw is that the validity of a filename is not required to be nondeterministic: a hypothetical file system might, for instance, not allow a deleted file to be replaced, or (in theory) could even randomly decide if a filename is valid.

As an alternative, it's fairly straightforward to create a method isInvalidFileName(String text) that returns true if the file is guaranteed to not be valid in Windows; filenames like "aux", "*", and "abc.txt." would return true. The file create operation would first check that the filename is guaranteed to be invalid and, if it returns false, would stop. Otherwise, the method could attempt to create the file, while being prepared for the edge case where the file cannot be created because the filename is invalid.

like image 31
drf Avatar answered Oct 13 '22 12:10

drf