在我的应用程序中,我从 LDAP 获取用户信息,有时完整的用户名采用错误的字符集。例如:
ТеÑÑ61 ТеÑÑовиÑ61
它也可以是英语或俄语并正确显示。如果用户名发生更改,则会在数据库中更新。即使我更改数据库中的值也无法解决问题。
我可以通过这样做在保存之前修复它
new String(incorrect.getBytes("ISO-8859-1"), "UTF-8");
但是,如果我将它用于包含俄语字符的字符串(例如,“Тест61 Тестович61”),我会得到类似这样的“????61 ?????????61”。
你能建议一些可以确定字符串字符集的东西吗?
据我所知,java 中的字符串不会保留其原始编码 - 它们始终以某种 Unicode 形式在内部存储。 您想要检测原始流/字节的字符集 - 这就是为什么我认为您的 String.toBytes() 调用为时已晚。
理想情况下,如果您可以获得正在读取的输入流,则可以通过以下方式运行它:http://code.google.com/p/juniversalchardet/
还有很多其他字符集检测器
我也有同样的问题。 Tika 太大,jununiversalchardet 无法检测到 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();
}
完整描述在这里:检测 Java 字符串中的字符集。
我推荐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");
我非常感谢 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;
}
您的 LDAP 数据库设置不正确。将数据放入其中的应用程序应转换为已知的字符集编码,在您的情况下,可能是 UTF_16。选择一个标准。所有检测编码的方法都是猜测。
写入值的应用程序是唯一明确知道它正在使用哪种编码并且可以正确转换为另一种编码(例如 UTF_16)的应用程序。
在您的网络应用程序中,您可以声明一个编码过滤器,以确保您以正确的编码接收数据。
<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 格式的参数。