35

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

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

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

我可以通过这样做在保存之前修复它

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

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

你能建议一些可以确定字符串字符集的东西吗?

4

6 回答 6

20

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

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

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

于 2012-07-16T04:54:47.990 回答
8

我有同样的问题。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

于 2017-12-13T10:07:29.353 回答
7

我推荐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");
于 2017-11-01T05:48:47.753 回答
3

我非常感谢 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;
}
于 2020-12-19T12:06:23.430 回答
2

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

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

于 2015-04-29T16:27:50.977 回答
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>

spring 提供的过滤器确保控制器/servlet 接收 UTF-8 格式的参数。

于 2012-07-16T06:10:09.973 回答