Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - How to find out whether a File name is valid? [duplicate]

Tags:

java

file

In my Java application I am renaming files to a file name provided in a String parameter. There is a method

boolean OKtoRename(String oldName, String newName) 

which basically checks whether the newName isn't already taken by some other file, as I wouldn't want to bury existing ones.

It now occurred to me that perhaps the newName String will not denote a valid file name. So I thought to add this check to the method:

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

Which obviously isn't the right way to do it, since in most cases the newFile does not yet exist and therefore although it is OKtoRename, the function returns false.

I was wondering, is there a method (I know there isn't for the java.io.File objects) like canExist()? Or would I have to resort to regex to make sure the newFile String does not contain invalid characters (e.g. ?, *, ", :)? I wonder if there is perhaps a function hidden somewhere in the JDK that would tell me if a string could possibly denote a valid file name.

like image 832
Peter Perháč Avatar asked May 21 '09 17:05

Peter Perháč


2 Answers

I assembled a list of illegal filename characters (considering UNIX, Mac OS X and Windows systems) based on some online research a couple of months ago. If the new filename contains any of these, there's a risk that it might not be valid on all platforms.

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

EDIT: I would like to stress, that this is not a complete solution: as a commenter pointed out, even though it passes this test your file name could still be a Windows specific keyword like COM, PRN, etc. However, if your file name contains any of these characters, it will certainly cause trouble in a cross-platform environment.

like image 70
Zsolt Török Avatar answered Oct 01 '22 11:10

Zsolt Török


Use createNewFile(), which will atomically create the file only if it doesn't yet exist.

If the file is created, the name is valid and it is not clobbering an existing file. You can then open the files and efficiently copy data from one to the other with FileChannel.transferXXX operations.

An important thing to keep in mind that, in general, the check and the creation should be atomic. If you first check whether an operation is safe, then perform the operation as a separate step, conditions may have changed in the meantime, making the operation unsafe.

Additional food for thought is available at this related post: "Move/Copy operations in Java."


Update:

Since this answer, the NIO.2 APIs have been introduced, which add more interaction with the file system.

Suppose you have an interactive program, and want to validate after each keystroke whether the file is potentially valid. For example, you might want to enable a "Save" button only when the entry is valid rather than popping up an error dialog after pressing "Save". Creating and ensuring the deletion of a lot of unnecessary files that my suggestion above would require seems like a mess.

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

However, there isn't an API to validate illegal names comprised of valid characters, like "PRN" on Windows. As a workaround, experimentation showed that using an illegal file name would raise a distinct exception when trying to access attributes (using Files.getLastModifiedTime(), for example).

If you specify a legal name for a file that does exist, you get no exception.

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

If you specify an illegal name, FileSystemException is raised.

However, this seems very kludgey and might not be reliable on other operating systems.

like image 20
erickson Avatar answered Oct 01 '22 10:10

erickson