从 Java 中删除无效文件名字符

在 Windows 下新建文件时,会发现部分特殊字符是不允许出现在文件名中的。

新建文件提示:

image-20210707105556980

修改文件提示:

image-20210707105604800

如果是程序通过字符串自动生成文件名,则需要对特殊字符进行过滤处理。

过滤特殊标点

fileName = fileName.replaceAll("[\\\\/:\\*\\?\\\"<>\\|]","")

过滤 Unicode

进一步测试发现,如果字符串中含有 Unicode 字符,也会密码失败:

String fileName = "测试Unicode\u0016.xls";

此时,需要对 Unicode 进行过滤:

fileName = fileName.replaceAll("[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]", "");
fileName = fileName.replaceAll("[\\uD83D\\uFFFD\\uFE0F\\u203C\\u3010\\u3011\\u300A\\u166D\\u200C\\u202A\\u202C\\u2049\\u20E3\\u300B\\u300C\\u3030\\u065F\\u0099\\u0F3A\\u0F3B\\uF610\\uFFFC]", "");

Windows 文件命名约定

Windows 对文件名的命名约定如下,参考

以下基本规则使应用程序可以为文件和目录创建和处理有效名称,而不考虑文件系统:

  • 使用句点将基文件名与目录或文件的名称中的扩展名分隔开来。

  • 使用反斜杠 () 分隔 路径组件。 反斜杠将文件名从路径中分隔到它,并将另一个目录名称从路径中的一个目录名称中分离。 不能在实际文件或目录的名称中使用反斜杠,因为它是将这些名称分隔到组件中的保留字符。

  • 根据需要使用反斜杠作为卷名的一部分,例如,"c: path file" 中的 "c:" 或 "服务器共享路径" 中的 "服务器 \ \ \ \ \ \ 共享" ( \ \ \ \ \ 适用于通用命名约定) (UNC) 名称。 有关 UNC 名称的详细信息,请参阅 最大路径长度限制 部分。

  • 不要假定区分大小写。 例如,将 OSCAR、Oscar 和 OSCAR 名称视为相同,即使某些文件系统 (例如 POSIX 兼容的文件系统,) 可能会将它们视为不同的。 请注意,NTFS 支持 POSIX 语义区分大小写,但这并不是默认行为。 有关详细信息,请参阅 CreateFile

  • 卷标识符 (驱动器号) 同样区分大小写。 例如,"D: \" 和 "d: \" 指的是同一个卷。

  • 在当前代码页中使用任何字符作为名称,包括 Unicode 字符和扩展字符集中的字符 (128 – 255) ,如下所示:

    • 以下保留字符:
      • <(小于)
      • > (大于)
      • : (冒号)
      • "(双引号)
      • /(正斜杠)
      • \ (反斜杠)
      • | (竖线或管道)
      • ? (问号)
      • * (星号)
    • 整数值零,有时称为 ASCII NUL 字符。
    • 其整数表示形式在 1 到 31 范围内的字符,除了允许使用这些字符的备用数据流。 有关文件流的详细信息,请参阅 文件流
    • 目标文件系统不允许的任何其他字符。
  • 使用句点作为路径中的目录 组件 来表示当前目录,例如 "。 \temp.txt"。 有关详细信息,请参阅 路径

  • 使用两个连续的句点 (。) 作为路径中的目录 组件 来表示当前目录的父目录,例如 ".。 \temp.txt"。 有关详细信息,请参阅 路径

  • 不要将以下保留名称用于文件的名称:

    CON、PRN、AUX、NUL、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8 和 LPT9。 还应避免使用后跟扩展名的这些名称;例如,不建议 NUL.txt。 有关详细信息,请参阅命名空间

  • 不要以空格或句点结束文件或目录名。 虽然底层文件系统可能支持这样的名称,但 Windows shell 和用户界面并不支持此类名称。 但是,可以将句点指定为名称的第一个字符。 例如 "temp"。

如果使用特殊保留字,则会出现异常:

image-20210707110331294

参考资料

  • Stack Overflow:how-to-remove-non-valid-unicode-characters-from-strings-in-java
  • java - 如何从 Java 中的字符串中删除无效的 Unicode 字符
  • 命名文件、路径和命名空间