일반적인 Java 웹 개발에서는 한자가 깨져서 문자로 변환되는 현상이 종종 발생합니다. 지금까지 헷갈려서 테스트 코드를 작성해 보았는데 드디어 인코딩을 명확하게 정리하고 먼저 결론을 내렸습니다.
utf8은 다양한 언어 인코딩을 저장합니다. 현재 utf8은 주류 개발에서 인코딩 및 디코딩에 사용됩니다. 다음 상황에서는 잘못된 코드가 발생합니다: 1, gbk(중국어), iso-8859-1(중국어 없음) 및 기타 인코딩 그렇지 않으면 문자가 깨집니다
2. 다른 방법으로 인코딩 및 디코딩에 utf8을 사용하면 문자가 깨져서 변환이 필요합니다
3. 해당 문자(중국어)가 없는 문자 집합(iso-8859-1)을 사용하면 코드가 깨져서 디코딩을 복원할 수 없습니다
다음은 위 상황에 대한 코드 테스트입니다
/** * 测试编码转换 中文 => utf-8 编码 - 解码 */ @Test public void test0() { String test = "测试"; System.out.println(Arrays.toString(test.getBytes(StandardCharsets.UTF_8)));//[-26, -75, -117, -24, -81, -107] System.out.println(new String(test.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));//测试 }
/** * 测试编码转换 中文 => gbk 编码 - 解码 */ @Test public void test1() throws UnsupportedEncodingException { String test = "测试"; System.out.println(Arrays.toString(test.getBytes("gbk")));//[-78, -30, -54, -44] System.out.println(new String(test.getBytes("gbk"), "GBK"));//测试 }
/** * 测试编码转换 中文 => utf-8 编码- gbk解码 */ @Test public void test2() throws UnsupportedEncodingException { String test = "测试"; System.out.println(Arrays.toString(test.getBytes(StandardCharsets.UTF_8)));//[-26, -75, -117, -24, -81, -107] System.out.println(new String(test.getBytes(StandardCharsets.UTF_8), "gbk"));//娴嬭瘯 }
올바른 방법은 잘못된 디코딩 형식(gbk)을 전송으로 누르고, 잘못된 형식(gbk)에 따라 다시 인코딩(utf8-encode)한 다음, utf8을 사용하여 올바른 디코딩(utf8-decode)을 수행하여 원본 문자를 가져옵니다
/** * 测试编码转换 中文 => utf-8 编码 - gbk 解码 ===> gbk 编码 - utf-8解码 * "测试" => (utf8-encode)[-26, -75, -117, -24, -81, -107] => (gbk-decode)娴嬭瘯 * "娴嬭瘯" => (utf8-encode)[-26, -75, -117, -24, -81, -107] => (utf8-decode)"测试" */ @Test public void test3() throws UnsupportedEncodingException { String test = "测试"; String test_gbk_utf8 = new String(test.getBytes(StandardCharsets.UTF_8), "gbk"); System.out.println(test_gbk_utf8);//娴嬭瘯 String test_utf8_gbk = new String(test_gbk_utf8.getBytes("gbk"), StandardCharsets.UTF_8); System.out.println(test_utf8_gbk);//测试 }
3. 해당 문자 인코딩이 없습니다
@Test public void test4() throws UnsupportedEncodingException { String test = "测试"; System.out.println(Arrays.toString(test.getBytes(StandardCharsets.ISO_8859_1)));//[63, 63] System.out.println(new String(test.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.ISO_8859_1));//?? }
이 경우 원래 인코딩 방법을 사용하여 디코딩하더라도 문자를 복원할 수 없습니다.
Java 인코딩 형식 변환 및 잘못된 코드 복구
Java에서 인코딩 형식 변환을 수행하는 방법
new String(str.getBytes("gbk"),"utf8")
String str="彩虹"; String [] a=new String[] {"gbk","unicode","utf8","gb2312"}; for (int i=0;i<a.length;i++){ for (int j=0;j<a.length;j++){ System.out.println("二进制格式: "+a[i]+"编码格式: "+a[j]); System.out.println("编码后的字符串: "+new String(str.getBytes(a[i]),a[j])); } }
인코딩 문자열: 닊뫧
바이너리 형식: gbk 인코딩 형식: utf8인코딩 문자열: �ʺ�바이너리 형식: gbk 인코딩 형식: gb2312
gbk는 gb2312의 향상된 버전이고 더 많은 한자를 지원하기 때문에 gbk와 gb2312 간의 변환에 잘못된 코드가 없습니다. 인코딩이므로 바이너리 인코딩 형식이 gbk이고 디코딩 형식이 gb2312인 경우 이러한 상황은 일부 한자가 깨졌을 가능성이 있습니다. 깨진 데이터를 다시 변환할 수 있습니까? 위 결과에서 깨진 문자는 대략 두 가지로 나눌 수 있습니까? 하나는 한자와 그래픽의 복잡한 조합이고, 다른 하나는 "?"입니다.
인코딩 문자열: Rainbow
바이너리 형식: 유니코드 인코딩 형식: gbk
인코딩된 문자열: �_i唝
바이너리 형식: 유니코드 인코딩 형식: unicode
인코딩 문자열: Rainbow
바이너리 형식: 유니코드 인코딩 형식: utf8
인코딩 문자열: ��_i�y
바이너리 형식: 유니코드 인코딩 형식: gb2312
인코딩된 문자열: ��_i�y
바이너리 형식: utf8 인코딩 형식: gbk
인코딩된 문자열: 褰╄櫣
바이너리 형식: utf8 인코딩 형식: unicode
인코딩된 문자열: ꧨ馹
바이너리 형식: utf8 인코딩 형식: utf8
인코딩된 문자열: Rainbow
바이너리 형식: utf8 인코딩 형식: gb2312
인코딩된 문자열:褰╄��
바이너리 형식: gb2312 인코딩 형식: gbk
인코딩된 문자열: Rainbow
바이너리 형식: gb2312 인코딩 형식: unicode
인코딩된 문자열: 닊뫧
바이너리 형식: gb2312 인코딩 형식: utf8
encoded 문자열: �ʺ�
바이너리 형식: gb2312 인코딩 형식: gb2312
인코딩 문자열: Rainbow
바이너리 인코딩 형식과 의 인코딩 형식이 다른 경우라고 볼 수 있습니다. 문자열이 다르면 잘못된 문자가 발생합니다.
gbk, gb2312 변환에 잘못된 코드가 없는 이유는 무엇입니까?
복구하려는 왜곡된 데이터에 물음표가 있으면 이 데이터를 제외하면 복구 가능성이 낮기 때문입니다. "?"의 경우 다른 왜곡된 문자에는 실제로 자체 인코딩 규칙이 있습니다. 이를 역디코딩하고 준수하는 한 올바른 인코딩 형식으로 다시 코딩하면 복원할 수 있습니다. 그러나 "?"는 예외입니다. 특정 인코딩 형식에 따라 인코딩 형식에 따라 의미 있는 문자로 변환할 수 없는 바이트 데이터의 바이트는 "?"로 변환되므로 바이트 스트림으로 역방향으로 인코딩되더라도 모두 "?" 동일한 바이트로 변환되므로 그 자체의 의미를 잃게 됩니다.
如果乱码中不包含"?",那么还是有希望转换回去的,我以上述乱码中的 "褰╄櫣" 为例重新进行了一次转换,代码如下:
String str="褰╄櫣"; String [] charset=new String[] {"gbk","unicode","utf8","gb2312"}; for (int i=0;i<charset.length;i++){ for (int j=0;j<charset.length;j++){ System.out.println("二进制格式: "+charset[i]+"编码格式: "+charset[j]); System.out.println("编码后的字符串: "+new String(str.getBytes(charset[i]),charset[j])); } }
二进制格式: gbk编码格式: gbk
编码后的字符串: 褰╄櫣
二进制格式: gbk编码格式: unicode
编码后的字符串: ꧨ馹
二进制格式: gbk编码格式: utf8
编码后的字符串: 彩虹
二进制格式: gbk编码格式: gb2312
编码后的字符串: 褰╄��
二进制格式: unicode编码格式: gbk
编码后的字符串: ��0%Dj�
二进制格式: unicode编码格式: unicode
编码后的字符串: 褰╄櫣
二进制格式: unicode编码格式: utf8
编码后的字符串: ���0%Dj�
二进制格式: unicode编码格式: gb2312
编码后的字符串: ���0%Dj�
二进制格式: utf8编码格式: gbk
编码后的字符串: 瑜扳晞娅�
二进制格式: utf8编码格式: unicode
编码后的字符串: 냢閄�
二进制格式: utf8编码格式: utf8
编码后的字符串: 褰╄櫣
二进制格式: utf8编码格式: gb2312
编码后的字符串: 瑜扳��娅�
二进制格式: gb2312编码格式: gbk
编码后的字符串: 褰╄?
二进制格式: gb2312编码格式: unicode
编码后的字符串: ꧨ�
二进制格式: gb2312编码格式: utf8
编码后的字符串: 彩�?
二进制格式: gb2312编码格式: gb2312
编码后的字符串: 褰╄?
可以看到 其中一种转换方式成功的将乱码转变回了正常的中文汉字
二进制格式: gbk编码格式: utf8
编码后的字符串: 彩虹
위 내용은 Java 인코딩 변환 프로세스는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!