我正在解析websocket消息并且由于在特定的socket.io版本中做了一个错误(不幸的是我无法控制服务器端),一些有效负载被双重编码为utf-8:
正确的值是Wrocławskiej(请注意l字母是LATIN SMALL LETTER L WITH STROKE)但实际上我回来了WrocÅawskiej。
我已经尝试用java再次解码/编码
String str = new String(wrongEncoded.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
不幸的是,字符串保持不变。关于如何在java中进行双重解码的任何想法?我看到了一个python版本,他们首先将它转换为raw_unicode
,然后再次解析它,但我不知道这是否有效,或者是否有类似的Java解决方案。
我已经阅读了关于该主题的几篇帖子,但没有人帮忙。
编辑:为了在Fiddler中澄清,我收到了上面提到的单词的以下字节序列:
WrocÃÂawskiej
byte[] arrOutput = { 0x57, 0x72, 0x6F, 0x63, 0xC3, 0x85, 0xC2, 0x82, 0x61, 0x77, 0x73, 0x6B, 0x69, 0x65, 0x6A };
答案 0 :(得分:4)
您的文本编码为UTF-8,然后将这些字节解释为ISO-8859-1并重新编码为UTF-8。
Wrocławskiej
是unicode:0057 0072 006f 0063 0142 0061 0077 0073 006b 0069 0065 006a
编码为UTF-8的是:57 72 6f 63 c5 82 61 77 73 6b 69 65 6a
在ISO-8859-1中,c5
为Å
,82
未定义。
作为ISO-8859-1,这些字节是:WrocÅawskiej
编码为UTF-8的是:57 72 6f 63 c3 85 c2 82 61 77 73 6b 69 65 6a
这些可能是你收到的字节。
所以,要撤消它,你需要:
String s = new String(bytes, StandardCharsets.UTF_8);
// fix "double encoding"
s = new String(s.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
答案 1 :(得分:0)
嗯,双重编码可能不是唯一要解决的问题。这是一个不止一个原因的解决方案
String myString = "heartbroken ð";
myString = new String(myString.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
String cleanedText = StringEscapeUtils.unescapeJava(myString);
byte[] bytes = cleanedText.getBytes(StandardCharsets.UTF_8);
String text = new String(bytes, StandardCharsets.UTF_8);
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
decoder.onMalformedInput(CodingErrorAction.IGNORE);
decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
CharsetEncoder encoder = charset.newEncoder();
encoder.onMalformedInput(CodingErrorAction.IGNORE);
encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
try {
// The new ByteBuffer is ready to be read.
ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(text));
// The new ByteBuffer is ready to be read.
CharBuffer cbuf = decoder.decode(bbuf);
String str = cbuf.toString();
} catch (CharacterCodingException e) {
logger.error("Error Message if you want to");
}
A
答案 2 :(得分:0)
我有一个问题,有时我会收到双重编码的字符串,有时会收到正确的编码的字符串。以下方法fixDoubleUTF8Encoding将正确处理这两种方法:
public static void main(String[] args) {
String input = "werewräüèö";
String result = fixDoubleUTF8Encoding(input);
System.out.println(result); // werewräüèö
input = "üäöé";
result = fixDoubleUTF8Encoding(input);
System.out.println(result); // üäöé
}
private static String fixDoubleUTF8Encoding(String s) {
// interpret the string as UTF_8
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
// now check if the bytes contain 0x83 0xC2, meaning double encoded garbage
if(isDoubleEncoded(bytes)) {
// if so, lets fix the string by assuming it is ASCII extended and recode it once
s = new String(s.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
}
return s;
}
private static boolean isDoubleEncoded(byte[] bytes) {
for (int i = 0; i < bytes.length; i++) {
if(bytes[i] == -125 && i+1 < bytes.length && bytes[i+1] == -62) {
return true;
}
}
return false;
}