有没有办法在java中实现字符集之间的字符转写?类似于 unix 命令(或类似的 php 函数)的东西:
iconv -f UTF-8 -t ASCII//TRANSLIT < some_doc.txt > new_doc.txt
最好在字符串上操作,与文件无关
我知道您可以使用String
构造函数更改编码,但这不能处理不在结果字符集中的字符的音译。
我不知道有任何库可以完全按照iconv
声称要做的事情(这似乎没有很好的定义)。但是,您可以在 Java 中使用“规范化”来执行诸如从字符中删除重音之类的操作。Unicode 标准很好地定义了这个过程。
我认为 NFKD(兼容性分解)后跟非 ASCII 字符的过滤可能会让你接近你想要的。显然,这是一个有损过程;您永远无法恢复原始字符串中的所有信息,所以要小心。
/* Decompose original "accented" string to basic characters. */
String decomposed = Normalizer.normalize(accented, Normalizer.Form.NFKD);
/* Build a new String with only ASCII characters. */
StringBuilder buf = new StringBuilder();
for (int idx = 0; idx < decomposed.length(); ++idx) {
char ch = decomposed.charAt(idx);
if (ch < 128)
buf.append(ch);
}
String filtered = buf.toString();
使用此处使用的过滤,您可能会使某些字符串不可读。例如,一串汉字将被完全过滤掉,因为它们都没有 ASCII 表示(这更像是 iconv's //IGNORE
)。
总体而言,构建自己的有效字符替换查找表或至少组合可安全剥离的字符(重音和事物)查找表会更安全。最佳解决方案取决于您希望处理的输入字符范围。
一种解决方案是将执行 iconv 作为外部进程执行。它肯定会冒犯纯粹主义者。它取决于系统上 iconv 的存在,但它可以正常工作并且完全符合您的要求:
public static String utfToAscii(String input) throws IOException {
Process p = Runtime.getRuntime().exec("iconv -f UTF-8 -t ASCII//TRANSLIT");
BufferedWriter bwo = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()));
bwo.write(input,0,input.length());
bwo.flush();
bwo.close();
String line = null;
StringBuilder stringBuilder = new StringBuilder();
String ls = System.getProperty("line.separator");
while( ( line = bri.readLine() ) != null ) {
stringBuilder.append( line );
stringBuilder.append( ls );
}
bri.close();
try {
p.waitFor();
} catch ( InterruptedException e ) {
}
return stringBuilder.toString();
}