在Java 6中识别依赖于操作系统的无效文件名字符(不适用于Java 7!)

3

目前我们有一组硬编码的字符需要检查--:*?"<>|/\--基本上是Windows会抱怨的那些字符。然而,在Linux上运行,这太过严格了。

我知道在Java 7 NIO中,Path类应该可以智能地以与操作系统相关的方式进行检查,并在指定无效文件名时抛出InvalidPathException异常。但我们没有运行Java 7。在Java 6中有可靠的方法来做到这一点吗?

(请注意,在Windows中使用new File("foo:bar")似乎是有效的。但如果您尝试使用FileWriter写入新的File时,实际上得到的是一个名为foo的空文件。此时,对File的exists()调用将返回true,但它或多或少是虚假的。)


2
利用NTFS的备用数据流功能。 - Jarekczek
@jarekczek -- 这是什么?我认为你的链接有问题。 - David Moles
2
一个冒号。https://dev59.com/1XI-5IYBdhLWcg3wiYza - Jarekczek
啊,好的。这就解释了 foo:bar 的奇怪之处。谢谢! - David Moles
3个回答

5
缺乏创意,这是我想到的 - 至少是其中的实质部分。
严格来说,可能是操作系统和文件系统的组合决定了无效字符集,但对于我的目的而言,仅基于操作系统的黑客攻击似乎已经足够好了。
此外,这些无效字符集是经验性的,而不是官方的。Windows的无效字符来自XP中当你试图将NTFS卷上的文件重命名为无效名称时所得到的错误消息。对于Unix/Linux,我认为你几乎可以使用任何字符,除了路径分隔符(如果您知道更好的,请纠正我)。对于MacOS,路径分隔符是否为“:”或“/”似乎取决于文件系统 - 对于我的目的,最安全的方法是包括两者(并希望它们没有挂载FAT或NTFS)。
List<Integer> invalidIndices = new LinkedList<Integer>();

String invalidChars;
if (OS.isWindows()) {
    invalidChars = "\\/:*?\"<>|";
} else if (OS.isMacOSX()) {
    invalidChars = "/:";
} else { // assume Unix/Linux
    invalidChars = "/";
}

char[] chars = filename.toCharArray();
for (int i = 0; i < chars.length; i++) {
    if ((invalidChars.indexOf(chars[i]) >= 0) // OS-invalid
        || (chars[i] < '\u0020') // ctrls
        || (chars[i] > '\u007e' && chars[i] < '\u00a0') // ctrls
    ) {
        invalidIndices.add(i);
    }
}

return invalidIndices;

注意:这里使用了 SwingX 的 OS 实用程序类来确定操作系统,但如果您没有它,它也不会有任何神奇的作用--只是解析 System.getProperty("os.name")

1

使用File.getCanonicalPath()方法可以在不需要创建文件的情况下完成此操作。

只需循环遍历每个可能的字符并存储结果即可。


0

如果想要解决这个问题,可以考虑查看Java7的源代码,并将其中一小部分(针对每个需要支持的操作系统)“回溯”到Java6中。

每个系统都应该有一个类,它扩展Path。我能快速找到的唯一来源是使用Google CodeSearch我的查询)的GaePath.java,它为GaeVFS实现了路径的内容。我不认为GaeVFS会引起您的兴趣,但是Java7的函数在Win32/UNIX/...上执行此操作必须在某个地方可用(可能是这里那里)。


我查找了一下,发现sun.nio.fs.WindowsPathParser和sun.nio.fs.UnixPath,但是它们似乎都没有做任何特别聪明的事情。这也许是好事,因为如果我复制/合并GPL代码,我的老板可能不会欣赏它。 :) - David Moles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接