Java – 如何找出文件名是否有效?

在我的Java应用程序中,我将文件重命名为String参数中提供的文件名。 有一种方法

boolean OKtoRename(String oldName, String newName) 

基本上检查newName是否已经被其他文件占用,因为我不想埋葬现有的文件。

现在我想到,也许newNamestring不会表示一个有效的文件名。 所以我想添加这个检查方法:

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

这显然不是正确的方法,因为在大多数情况下,newFile还不存在,因此虽然 OKtoRename,但函数返回false。

我想知道,是否有一个方法(我知道有没有java.io.File对象)像canExist() ? 或者我将不得不求助于正则expression式来确保newFilestring不包含无效字符(例如,?,*,“,:)?我想知道是否有一个隐藏在JDK的某个地方,可以告诉我,如果一个string可能表示一个有效的文件名。

使用createNewFile() ,只有在文件还不存在的情况下才会自动创build文件。

如果文件被创build,名称是有效的,并且不会破坏现有的文件。 然后,您可以使用FileChannel.transferXXX操作打开文件并高效地将数据从一个文件复制到另一个文件。

一个重要的事情要记住,一般来说,检查和创造应该是primefaces的。 如果首先检查一个操作是否安全,则作为一个单独的步骤执行操作,同时条件可能已经改变,使操作不安全。

在这篇相关的文章中提供了更多的思考: “在Java中移动/复制操作”。


更新:

由于这个答案,已经引入了NIO.2 API,这增加了与文件系统的更多交互。

假设你有一个交互式程序,并且想要在每次按键之后validation文件是否有效。 例如,您可能只想在条目有效时启用“保存”button,而不是在按下“保存”后popup错误对话框。 创build并确保删除大量不必要的文件,我的build议上面会需要看起来像一团糟。

使用NIO.2,不能创build包含文件系统非法字符的Path实例。 尝试创buildPath立即引发InvalidPathException

但是,没有API来validation由有效字符组成的非法名称,如Windows上的“PRN”。 作为一种解决方法,实验表明,使用非法文件名会在尝试访问属性时引发一个明显的exceptionFiles.getLastModifiedTime()例如使用Files.getLastModifiedTime() )。

如果您为存在的文件指定合法名称,则不会有任何exception。

如果您为不存在的文件指定合法名称,则会引发NoSuchFileException

如果指定了非法名称,则引发FileSystemException

但是,这看起来很杂乱,在其他操作系统上可能不可靠。

基于几个月前的在线研究,我汇集了非法文件名字符(考虑UNIX,Mac OS X和Windows系统)的列表。 如果新文件名包含其中的任何一个,则可能会在所有平台上无效。

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

编辑:我想强调,这不是一个完整的解决scheme :作为一个评论者指出,即使它通过这个testing您的文件名仍然可以是一个Windows特定的关键字,如COM,PRN等。但是,如果您的文件名称包含这些字符中的任何一个,它在跨平台环境中肯定会造成麻烦。

这里build议系统特定的方法。

 public static boolean isFilenameValid(String file) { File f = new File(file); try { f.getCanonicalPath(); return true; } catch (IOException e) { return false; } } 

这是我如何实现这一点:

 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; } 

如果为Eclipse开发,请查看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; } } 

只是我发现,在Java 7和更高版本中,有一个叫Paths的类有一个get方法,它接受一个或多个String和throws

InvalidPathException – 如果pathstring不能转换为path

对我来说,这似乎是一个操作系统相关的问题。 您可能只是想检查文件名中的一些无效字符。 Windows在尝试重命名文件时会执行此操作,它会popup一条消息,指出文件不能包含以下任何字符:\ /:*? <> | 我不确定你的问题是“是否有图书馆为我工作?” 在这种情况下,我不知道。

运用

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

做的工作。

我今天刚刚find 我不确定它是否能100%的工作,但到目前为止,我已经能够创build有效的文件名。