Java - 如何确定文件名是否有效?

2022-08-31 17:09:57

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

boolean OKtoRename(String oldName, String newName)

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

现在我突然想到,也许 newName String 不会表示有效的文件名。所以我想把这个检查添加到方法中:

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

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

我想知道,有没有一种方法(我知道没有java.io.File对象)像?或者我必须诉诸正则表达式来确保newFile字符串不包含无效字符(例如?,*,“,:)?我想知道JDK中是否有一个隐藏在某个地方的函数,可以告诉我字符串是否可以表示有效的文件名。canExist()


答案 1

几个月前,我根据一些在线研究收集了一个非法文件名字符列表(考虑到UNIX,Mac OS X和Windows系统)。如果新文件名包含其中任何一个,则存在它可能并非在所有平台上都有效的风险。

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

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


答案 2

使用 createNewFile(),仅当文件尚不存在时,它才会以原子方式创建该文件。

如果创建了该文件,则该名称有效,并且不会破坏现有文件。然后,您可以打开文件,并通过操作有效地将数据从一个文件复制到另一个文件。FileChannel.transferXXX

要记住的重要一点是,一般来说,检查和创建应该是原子的。如果首先检查某个操作是否安全,然后将该操作作为单独的步骤执行,则在此期间条件可能已更改,从而使操作不安全。

其他值得思考的内容可以在这篇相关文章中找到:“Java中的移动/复制操作”。


更新:

从这个答案开始,NIO.2 API被引入,增加了与文件系统的更多交互。

假设您有一个交互式程序,并且希望在每次击键后验证该文件是否可能有效。例如,您可能希望仅在条目有效时才启用“保存”按钮,而不是在按“保存”后弹出错误对话框。创建并确保删除我上面的建议所需的大量不必要的文件似乎是一团糟。

使用 NIO.2,您无法创建包含对文件系统非法的字符的实例。一旦您尝试创建 .PathInvalidPathExceptionPath

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

如果为确实存在的文件指定合法名称,则不会遇到任何例外。

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

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

但是,这似乎非常笨拙,在其他操作系统上可能不可靠。