java中是否有与//translat等效的iconv?

java中是否有与//translat等效的iconv?,java,iconv,Java,Iconv,有没有一种方法可以在java中实现字符集之间的音译?类似于unix命令(或类似的php函数)的内容: iconv-f UTF-8-t ASCII//translatitnew_doc.txt 最好是在字符串上操作,与文件无关 我知道您可以使用字符串构造函数更改编码,但这不能处理不在结果字符集中的字符的音译。我不知道有任何库可以完全按照iconv的要求来做(这似乎定义得不太好)。但是,您可以在Java中使用来做一些事情,比如从字符中删除重音符号。Unicode标准很好地定义了这个过程 我认为NF

有没有一种方法可以在java中实现字符集之间的音译?类似于unix命令(或类似的php函数)的内容:

iconv-f UTF-8-t ASCII//translatitnew_doc.txt
最好是在字符串上操作,与文件无关


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

我不知道有任何库可以完全按照
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();
/*将原始“重音”字符串分解为基本字符*/
字符串分解=Normalizer.normalize(重音,Normalizer.Form.NFKD);
/*仅使用ASCII字符生成新字符串*/
StringBuilder buf=新的StringBuilder();
对于(int idx=0;idx
使用此处使用的过滤,可能会使某些字符串无法读取。例如,一个汉字字符串将被完全过滤掉,因为它们都没有ASCII表示(这更像iconv的
//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();
}

让我们从Ericson答案的细微变化开始,并在此基础上构建更多的
//translatit
功能:

分解字符以获得ASCII-
字符串
公共类translatit{
私有静态最终字符集US_ASCII=Charset.forName(“US-ASCII”);
私有静态字符串toAscii(最终字符串输入){
最终CharsetEncoder CharsetEncoder=US_ASCII.newEncoder();
final char[]decomposed=Normalizer.normalize(输入,Normalizer.Form.NFKD).toCharArray();
最终StringBuilder sb=新StringBuilder(分解长度);
对于(int i=0;i”+toAscii(a));
System.out.println(a.toUpperCase()+“=>”+toAscii(a.toUpperCase());
}
}
虽然US-ASCII的行为应该相同,但对于不同的目标编码,该解决方案更容易采用。(由于首先分解字符,因此对于其他编码,这不一定会产生更好的结果)

该函数对于补充代码点是安全的(对于ASCII作为目标而言,这有点过分,但如果选择另一个目标编码,则可能会减少头痛)

还要注意,返回的是一个常规Java字符串;如果您需要ASCII-
字节[]
您仍然需要对其进行转换(但我们已确保没有违规字符…)

这就是如何将其扩展到更多字符集的方法:

替换或分解字符以获得可在提供的
字符集中编码的
字符串
import java.nio.CharBuffer;
导入java.nio.charset.charset;
导入java.nio.charset.CharsetEncoder;
导入java.text.Normalizer;
导入java.util.Collections;
导入java.util.HashMap;
导入java.util.Map;
/**
*创建用于http://stackoverflow.com/a/22841035/1266906
*/
公共类翻译{
公共静态最终字符集US_ASCII=Charset.forName(“US-ASCII”);
公共静态最终字符集ISO_8859_1=Charset.forName(“ISO-8859-1”);
公共静态最终字符集UTF_8=Charset.forName(“UTF-8”);
public static final HashMap REPLACEMENTS=new ReplacementBuilder().put(“-”,““”)
.put(“,”)
.put(“,”)
.put(‘〃’、‘〃’)
.put(欧元、欧元)
.put(‘ß’,‘ss’)
.put(“•”、“*”)
.getMap();
私有静态字符串toCharset(最终字符串输入,字符集字符集){
返回到harset(输入、字符集、Collections.emptyMap());
}
专用静态字符串toCharset(最终字符串输入,
字符集字符集,

谢谢埃里克森给我的提示。我遇到的最麻烦的角色
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();
}