15

有没有办法在java中实现字符集之间的字符转写?类似于 unix 命令(或类似的 php 函数)的东西:

iconv -f UTF-8 -t ASCII//TRANSLIT < some_doc.txt  > new_doc.txt

最好在字符串上操作,与文件无关

我知道您可以使用String构造函数更改编码,但这不能处理不在结果字符集中的字符的音译。

4

3 回答 3

11

我不知道有任何库可以完全按照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)。

总体而言,构建自己的有效字符替换查找表或至少组合可安全剥离的字符(重音和事物)查找表会更安全。最佳解决方案取决于您希望处理的输入字符范围。

于 2011-04-27T16:30:29.760 回答
5

一种解决方案是将执行 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();
}
于 2012-03-19T15:11:44.340 回答
5
于 2014-04-03T14:40:08.927 回答