如何将任何语言和字符集中的字符串转换为Java中的有效文件名?

ler*_*ros 6 java unicode filenames internationalization

我需要从用户输入的名称生成文件名.这些名称可以是任何语言.例如:

  • "约翰·史密斯"
  • "高冈和子"
  • "محمدسعيدبنعبدالعزيزالفلسطيني"

这些都是使用输入的值,所以我不能保证名称不包含文件名无效的字符.

用户将从他们的浏览器下载这些文件,因此我需要确保文件名在所有配置的所有操作系统上都有效.

我目前正在为英语国家做这个,只需用一个简单的正则表达式删除所有非字母数字字符:

string = string.replaceAll("[^a-zA-Z0-9]", "");
string = string.replaceAll("\\s+", "_")
Run Code Online (Sandbox Code Playgroud)

一些示例转换:

  • "John Smith" - >"John_Smith.ext"
  • "John O'Henry" - >"John_OHenry.ext"
  • "John van Smith III" - >"John_van_Smith_III.ext"

显然这在国际上不起作用.

我已经考虑过查找/生成所有文件系统中无效的所有字符的黑名单,并从名称中删除这些字符.我一直无法找到一份全面的清单.

如果可能的话,我更愿意在公共库中使用现有代码.我想这是一个已经解决的问题,但我无法找到一个国际化的解决方案.

文件名是供用户下载文件的,不适合我.我不打算存储这些文件.这些文件由服务器根据数据库中的数据请求动态生成.文件名是为了方便下载文件的人.

ecl*_*cle 4

正则表达式[^a-zA-Z0-9]将过滤非 ASCII 字符,从而忽略 Unicode 字符或超过 128 个代码点的字符。

\n\n

假设您想要通过替换无效的文件名字符(例如? \\ / : | < > *下划线 ( _))来过滤用户输入的有效文件名:

\n\n
import java.io.UnsupportedEncodingException;\n\npublic class ReplaceI18N {\n\n    public static void main(String[] args) {\n        String[] names = {\n                "John Smith",\n                "\xe9\xab\x98\xe5\xb2\xa1\xe5\x92\x8c\xe5\xad\x90",\n                "\xd9\x85\xd8\xad\xd9\x85\xd8\xaf \xd8\xb3\xd8\xb9\xd9\x8a\xd8\xaf \xd8\xa8\xd9\x86 \xd8\xb9\xd8\xa8\xd8\xaf \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb2\xd9\x8a\xd8\xb2 \xd8\xa7\xd9\x84\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\xd9\x8a",                \n                "|J:o<h>n?Sm\\\\it/h*", \n                "\xe9\xab\x98?\xe5\xb2\xa1\xe5\x92\x8c\\\\\xe5\xad\x90*", \n                "\xd9\x85\xd8\xad\xd9\x85\xd8\xaf /\xd8\xb3\xd8\xb9\xd9\x8a\xd8\xaf \xd8\xa8\xd9\x86 \xd8\xb9\xd8\xa8\xd8\xaf ?\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb2\xd9\x8a\xd8\xb2 :\xd8\xa7\xd9\x84\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\xd9\x8a\\\\"\n                };\n\n        for(String s: names){\n            String u  = s;\n            try {\n                u = new String(s.getBytes(), "UTF-8");\n            } catch (UnsupportedEncodingException e) {\n                // TODO Auto-generated catch block\n                e.printStackTrace();\n            } \n            u = u.replaceAll("[\\\\?\\\\\\\\/:|<>\\\\*]", " "); //filter ? \\ / : | < > *\n            u = u.replaceAll("\\\\s+", "_");\n            System.out.println(s + " = " + u);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
John Smith = John_Smith\n\xe9\xab\x98\xe5\xb2\xa1\xe5\x92\x8c\xe5\xad\x90 = \xe9\xab\x98\xe5\xb2\xa1\xe5\x92\x8c\xe5\xad\x90\n\xd9\x85\xd8\xad\xd9\x85\xd8\xaf \xd8\xb3\xd8\xb9\xd9\x8a\xd8\xaf \xd8\xa8\xd9\x86 \xd8\xb9\xd8\xa8\xd8\xaf \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb2\xd9\x8a\xd8\xb2 \xd8\xa7\xd9\x84\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\xd9\x8a = \xd9\x85\xd8\xad\xd9\x85\xd8\xaf_\xd8\xb3\xd8\xb9\xd9\x8a\xd8\xaf_\xd8\xa8\xd9\x86_\xd8\xb9\xd8\xa8\xd8\xaf_\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb2\xd9\x8a\xd8\xb2_\xd8\xa7\xd9\x84\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\xd9\x8a\n|J:o<h>n?Sm\\it/h* = _J_o_h_n_Sm_it_h_\n\xe9\xab\x98?\xe5\xb2\xa1\xe5\x92\x8c\\\xe5\xad\x90* = \xe9\xab\x98_\xe5\xb2\xa1\xe5\x92\x8c_\xe5\xad\x90_\n\xd9\x85\xd8\xad\xd9\x85\xd8\xaf /\xd8\xb3\xd8\xb9\xd9\x8a\xd8\xaf \xd8\xa8\xd9\x86 \xd8\xb9\xd8\xa8\xd8\xaf ?\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb2\xd9\x8a\xd8\xb2 :\xd8\xa7\xd9\x84\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\xd9\x8a\\ = \xd9\x85\xd8\xad\xd9\x85\xd8\xaf_\xd8\xb3\xd8\xb9\xd9\x8a\xd8\xaf_\xd8\xa8\xd9\x86_\xd8\xb9\xd8\xa8\xd8\xaf_\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb2\xd9\x8a\xd8\xb2_\xd8\xa7\xd9\x84\xd9\x81\xd9\x84\xd8\xb3\xd8\xb7\xd9\x8a\xd9\x86\xd9\x8a_\n
Run Code Online (Sandbox Code Playgroud)\n\n

即使包含 Unicode 字符,有效的文件名也可以在任何支持 UTF-8 编码且具有正确 Unicode 字体的网页上显示。

\n\n

此外,每个支持 Unicode 的操作系统文件系统上的文件名都是正确的(在 Windows XP、Windows 7 上测试正常)。

\n\n

国际化文件名

\n\n

但是,如果您想将每个有效文件名作为 URL 字符串传递,请确保使用 对其进行正确编码URLEncoder,然后使用URLDecoder.

\n