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

如何在Java中检查字符串的字符集?,java,string,character-encoding,Java,String,Character Encoding,在我的应用程序中,我从LDAP获取用户信息,有时完整用户名出现在错误的字符集中。例如: ТеÑÑ61 ТеÑÑовиÑ61 它也可以是英语或俄语,并正确显示。如果用户名更改,它将在数据库中更新。即使我改变db中的值,也不能解决问题 通过这样做,我可以在保存之前修复它 new String(incorrect.getBytes("ISO-8859-1"), "UTF-8"); 但是,如果我将其用于包含俄语字符的字符串(例如,“tit挈挈挈61 tit挈挈挈61”),我会得到这样的

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

ТеÑÑ61 ТеÑÑовиÑ61
它也可以是英语或俄语,并正确显示。如果用户名更改,它将在数据库中更新。即使我改变db中的值,也不能解决问题

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

new String(incorrect.getBytes("ISO-8859-1"), "UTF-8");
但是,如果我将其用于包含俄语字符的字符串(例如,“tit挈挈挈61 tit挈挈挈61”),我会得到这样的结果“????61?????”


您能建议一些可以确定字符串字符集的方法吗?

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

理想情况下,如果您可以获取正在读取的输入流,您可以通过以下方式运行它:


在您的web应用程序中还有许多其他字符集检测器,您可以声明一个编码过滤器,以确保以正确的编码接收数据


显式地将页面的编码设置为UTF-8
编码滤波器
org.springframework.web.filter.CharacterEncodingFilter
编码
UTF-8
强制编码
真的

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

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

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

我推荐,非常友好和强大

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

我也有同样的问题。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();
}

这里的完整描述:。

我非常感谢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;
}
私有字符串转换(字符串值、字符集fromEncoding、字符集toEncoding)引发不支持的编码异常{
返回新字符串(value.getBytes(fromEncoding),toEncoding);
}
私有布尔探测(字符串值,字符集字符集)引发UnsupportedEncodingException{
字符集探测=StandardCharsets.UTF_8;
返回值.equals(convert(convert(value,charset,probe),probe,charset));
}
公共字符串转换(字符串值、Charset charsetWanted、List CharsetOther)引发UnsupportedEncodingException{
if(探测(值,字符集){
返回值;
}
for(字符集其他:字符集其他){
if(探头(值,其他)){
返回转换(值、其他、字符集);
}
}
System.err.println(“警告:无法转换字符串:“+值”);
返回值;
}

哦,不,我从来没有注意到这一点,但我一直在为答案投票。现在我知道了,谢谢你为我指出。非常感谢你的帮助!我不确定是否可以获取输入流cas,因为用户数据是使用UserService从上下文中获取的。另一种方法可能是修复LDAP中的值。这只适用于spring应用程序。此外,如果使用基本身份验证,强制编码可能不起作用。此库将向最终二进制文件添加45 Mb!您是否尝试过在
for
循环中使用大型
字符串和大量字符集?够快吗?
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;
}