如何在Java中检查字符串的字符集?

时间:2012-07-16 03:53:55

标签: java string character-encoding

在我的应用程序中,我从LDAP获取用户信息,有时完整的用户名出现在错误的字符集中。例如:

ТеÑÑ61 ТеÑÑовиÑ61

它也可以是英文或俄文并正确显示。如果用户名更改,则会在数据库中更新。即使我更改了db中的值,它也不会解决问题。

我可以通过执行此操作来修复它

new String(incorrect.getBytes("ISO-8859-1"), "UTF-8");

但是,如果我将它用于包含俄语字符的字符串(例如,“Тест61Тестович61”),我会得到类似这样的内容“???? 61 ???????? 61”。< / p>

你能否提出一些可以确定字符串字符集的内容?

6 个答案:

答案 0 :(得分:13)

java中的字符串AFAIK不保留其原始编码 - 它们始终以某种Unicode格式存储在内部。 你想检测原始流/字节的字符集 - 这就是我认为你的String.toBytes()调用为时已晚的原因。

理想情况下,如果您可以获取正在阅读的输入流,则可以通过以下方式运行:http://code.google.com/p/juniversalchardet/

还有很多其他的字符集探测器

答案 1 :(得分:2)

我推荐Apache.tika CharsetDetector,非常友好和强大。

CharsetDetector detector = new CharsetDetector();
detector.setText(yourStr.getBytes());
detector.detect();  // <- return the result, you can check by .getName() method

此外,您可以将任何编码的字符串转换为您想要的字符串,以utf-8为例:

detector.getString(yourStr.getBytes(), "utf-8");

答案 2 :(得分:2)

我遇到了同样的问题。 Tika太大,juniversalchardet没有检测到ISO-8859-1。所以,我做了自己,现在在生产中运作良好:

public String convert(String value, String fromEncoding, String toEncoding) {
  return new String(value.getBytes(fromEncoding), toEncoding);
}

public String charset(String value, String charsets[]) {
  String probe = StandardCharsets.UTF_8.name();
  for(String c : charsets) {
    Charset charset = Charset.forName(c);
    if(charset != null) {
      if(value.equals(convert(convert(value, charset.name(), probe), probe, charset.name()))) {
        return c;
      }
    }
  }
  return StandardCharsets.UTF_8.name();
}

完整说明:Detect the charset in Java strings

答案 3 :(得分:2)

我非常感谢 Lluís Turró Cutiller 的回答 (+1),但想在此基础上添加一个变体。

private String convert(String value, Charset fromEncoding, Charset toEncoding) throws UnsupportedEncodingException {
    return new String(value.getBytes(fromEncoding), toEncoding);
}

private boolean probe(String value, Charset charset) throws UnsupportedEncodingException {
    Charset probe = StandardCharsets.UTF_8;
    return value.equals(convert(convert(value, charset, probe), probe, charset));
}

public String convert(String value, Charset charsetWanted, List<Charset> charsetsOther) throws UnsupportedEncodingException {
    if (probe(value, charsetWanted)) {
        return value;
    }
    for (Charset other: charsetsOther) {
        if (probe(value, other)) {
            return convert(value, other, charsetWanted);
        }
    }
    System.err.println("WARNING: Could not convert string: " + value);
    return value;
}

答案 4 :(得分:1)

您的LDAP数据库设置不正确。将数据放入其中的应用程序应该转换为已知的字符集编码,在您的情况下,可能是UTF_16。选择一个标准。所有检测编码的方法都是猜测。

编写该值的应用程序是唯一一个明确知道它正在使用哪种编码并且可以正确转换为其他编码(例如UTF_16)的应用程序。

答案 5 :(得分:0)

在您的网络应用程序中,您可以声明一个编码过滤器,确保您以正确的编码方式接收数据。

<filter>
    <description>Explicitly set the encoding of the page to UTF-8</description>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

弹簧提供的过滤器确保控制器/ servlet接收UTF-8中的参数。