[英]Java Decode double encoded utf-8 char
我正在解析一個 websocket 消息,並且由於在特定的 socket.io 版本中做了一個錯誤(不幸的是我無法控制服務器端),一些有效負載被雙重編碼為 utf-8:
正確的值應該是Wrocławskiej (注意 l 字母,它是帶有中風的拉丁文小寫字母 L)但我實際上得到了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 };
您的文本編碼為 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);
我遇到的問題是有時我收到雙重編碼的字符串,有時收到正確的編碼字符串。 以下方法 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;
}
好吧,雙重編碼可能不是唯一需要處理的問題。 這是一個解決方案,其原因不止一個
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");
}
一
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.