Java - How do I know if a file name is valid?

In my Java application, I rename files to the file name represented by the String parameter. There is a method

boolean OKtoRename(String oldName, String newName) 

which basically checks if newName is not yet some other file, since I would not want to bury the existing ones.

Now it occurred to me that perhaps the newName String would not indicate a valid file name. So I decided to add this check to the method:

 if (new File(newName).isFile()) { return false; } 

Obviously, this is the wrong way to do this, since in most cases newFile does not exist yet and therefore, although it is OKtoRename, the function returns false.

I was wondering if there is a method (I know what is not for java.io.File objects) like canExist() ? Or will I have to resort to a regular expression to make sure that the newFile String does not contain any invalid characters (like ?, *, ", :)? I wonder if there is any function hidden somewhere in the JDK that will tell me if the string may mean a valid file name.

+43
java file
May 21 '09 at 17:04
source share
8 answers

Use createNewFile() , which will atomize the file only if it does not already exist.

If the file is created, the name is valid and does not kill the existing file. Then you can open files and efficiently copy data from one to another using FileChannel.transferXXX operations.

It is important to remember that in general, verification and creation should be atomic. If you first check if the operation is safe, then perform the operation as a separate step, the conditions can be changed at the same time, which makes the operation unsafe.

Further information on food can be found in this related entry: "Move / Copy Operations in Java."




Update:

Following this answer, NIO.2 APIs were introduced that add more interaction to the file system.

Suppose you have an interactive program and want to check after each keystroke that the file is potentially valid. For example, you can enable the “Save” button only when the record is valid, and a dialog box with an error message after clicking “Save” does not appear. Creating and securing the removal of the large number of junk files that my suggestion above would require seems like a mess.

With NIO.2, you cannot create a Path instance containing characters that are illegal for the file system. InvalidPathException is InvalidPathException as soon as you try to create a Path .

However, the API does not check illegal names consisting of valid characters, such as "PRN" on Windows. As a workaround, experimentation showed that using an invalid file name would throw a separate exception when trying to access attributes (for example, using Files.getLastModifiedTime() ).

If you provide a legal name for a file that exists, you will not receive any exception.

If you specify a legal name for a file that does not exist, it raises a NoSuchFileException .

If you specify an illegal name, a FileSystemException will be raised.

However, this seems very kludgey and can be unreliable on other operating systems.

+20
May 21 '09 at 17:06
source share

I put together a list of illegal file names (including UNIX, Mac OS X, and Windows systems) based on some online research a couple of months ago. If the new file name contains any of them, there is a risk that it may be invalid on all platforms.

 private static final char[] ILLEGAL_CHARACTERS = { '/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':' }; 

EDIT: I would like to emphasize that this is not a complete solution : as the commentator noted, even though he passed this test, your file name may still be key for Windows, such as COM, PRN, etc. However, if your file name contains any of these characters, this will certainly cause problems in a cross-platform environment.

+54
May 21 '09 at 17:33
source share

A specific system method is proposed here.

 public static boolean isFilenameValid(String file) { File f = new File(file); try { f.getCanonicalPath(); return true; } catch (IOException e) { return false; } } 
+16
Nov 04 2018-11-11T00:
source share

Here is how I did it:

 public boolean isValidFileName(final String aFileName) { final File aFile = new File(aFileName); boolean isValid = true; try { if (aFile.createNewFile()) { aFile.delete(); } } catch (IOException e) { isValid = false; } return isValid; } 
+4
Jul 27. 2018-11-11T00:
source share

If you are developing for Eclipse check out org.eclipse.core.internal.resources.OS

 public abstract class OS { private static final String INSTALLED_PLATFORM; public static final char[] INVALID_RESOURCE_CHARACTERS; private static final String[] INVALID_RESOURCE_BASENAMES; private static final String[] INVALID_RESOURCE_FULLNAMES; static { //find out the OS being used //setup the invalid names INSTALLED_PLATFORM = Platform.getOS(); if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) { //valid names and characters taken from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp INVALID_RESOURCE_CHARACTERS = new char[] {'\\', '/', ':', '*', '?', '"', '<', '>', '|'}; INVALID_RESOURCE_BASENAMES = new String[] {"aux", "com1", "com2", "com3", "com4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ "com5", "com6", "com7", "com8", "com9", "con", "lpt1", "lpt2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "nul", "prn"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ Arrays.sort(INVALID_RESOURCE_BASENAMES); //CLOCK$ may be used if an extension is provided INVALID_RESOURCE_FULLNAMES = new String[] {"clock$"}; //$NON-NLS-1$ } else { //only front slash and null char are invalid on UNIXes //taken from http://www.faqs.org/faqs/unix-faq/faq/part2/section-2.html INVALID_RESOURCE_CHARACTERS = new char[] {'/', '\0',}; INVALID_RESOURCE_BASENAMES = null; INVALID_RESOURCE_FULLNAMES = null; } } /** * Returns true if the given name is a valid resource name on this operating system, * and false otherwise. */ public static boolean isNameValid(String name) { //. and .. have special meaning on all platforms if (name.equals(".") || name.equals("..")) //$NON-NLS-1$ //$NON-NLS-2$ return false; if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) { //empty names are not valid final int length = name.length(); if (length == 0) return false; final char lastChar = name.charAt(length-1); // filenames ending in dot are not valid if (lastChar == '.') return false; // file names ending with whitespace are truncated (bug 118997) if (Character.isWhitespace(lastChar)) return false; int dot = name.indexOf('.'); //on windows, filename suffixes are not relevant to name validity String basename = dot == -1 ? name : name.substring(0, dot); if (Arrays.binarySearch(INVALID_RESOURCE_BASENAMES, basename.toLowerCase()) >= 0) return false; return Arrays.binarySearch(INVALID_RESOURCE_FULLNAMES, name.toLowerCase()) < 0; } return true; } } 
+4
Mar 11 '15 at 21:10
source share

It seems to me that this is an OS-specific issue. You may just want to check for an invalid character in the file name. Windows does this when trying to rename a file, a message appears stating that the file cannot contain any of the following characters: \ /: *? <> | I'm not sure your question is: "Is there a library for me?" in this case I don’t know.

+2
May 21 '09 at 18:00
source share

Just something I found, in java 7 and later there is a class called Paths that has a method called get that takes one or more String and throws

InvalidPathException - if the path string cannot be converted to Path

+2
May 6 '15 at 20:35
source share

Using

 String validName = URLEncoder.encode( fileName , "UTF-8"); File newFile = new File( validName ); 

Does it work.

I just found today. I'm not sure if it works in 100% of cases, but so far I have managed to create the correct file names.

0
May 26 '09 at 17:46
source share



All Articles