另有一篇我的字符编码本质入门的文章见这里:https://www.cnblogs.com/uncleguo/p/16008551.html
实话说,作为一个多年Java老年程序员,直到近来,在没有决心花时间搞清楚Java String的编码相关问题之前, 自己也都还是似懂非懂,一脸懵逼的。设想如果在面试中,有同学能够条理清晰的回答下面的问题,那必是非常了得之人,论智慧武功应该均在本人之上:-)。
问:请预测下面程序的输出,并解释原因。printHexBinary方法为16进制打印Byte
1 String str = "中"; 2 3byte[] bufferGBK = str.getBytes("GBK"); 4 System.out.println("bufferGBK = "+printHexBinary(bufferGBK)) ; 5 6 String gbkString =new String(bufferGBK,"GBK"); 7 System.out.println("gbkString = new String bufferGBK GBK : "+gbkString); 8 9 String utf8String =new String(bufferGBK,"utf-8");10 System.out.println("utf8String = new String bufferGBK utf8 : "+utf8String);1112byte[] utfFromStr = utf8String.getBytes("utf-8");13 System.out.println("utf8String getBytes utf-8 : "+printHexBinary(utfFromStr));1415byte[] gbkFromStr = utf8String.getBytes("GBK");16 System.out.println("utf8String getBytes GBK : "+printHexBinary(gbkFromStr));1718byte[] isoFromStr = utf8String.getBytes("ISO-8859-1");19 System.out.println("utf8String getBytes ISO-8859-1 : "+printHexBinary(isoFromStr));2021 String isoString =new String(bufferGBK,"ISO-8859-1");22 System.out.println("isoString = new String bufferGBK ISO-8859-1 : "+isoString);2324 utfFromStr = isoString.getBytes("utf-8");25 System.out.println("isoString getBytes utf-8 : "+printHexBinary(utfFromStr));2627 gbkFromStr = isoString.getBytes("GBK");28 System.out.println("isoString getBytes GBK : "+printHexBinary(gbkFromStr));2930 isoFromStr = isoString.getBytes("ISO-8859-1");31 System.out.println("isoString getBytes ISO-8859-1 : "+printHexBinary(isoFromStr));
按我之前的认识,先简单推理下。
第4行的Print输出的应该是“中”的GBK编码(中的GBK编码是0xD6 0xD0)。
第7行用[0xD6 0xD0]以GBK字符集new一个String,打印这个String,那应该是“中”
第10行用[0xD6 0xD0]以UTF8字符集new一个String,打印这个String,这里可能会乱码,具体会显示什么字符,要看0xD6 0xD0对应的Utf8 字符。
× 第13行从上面new的String中按UTF8取得Byte数组,因为上面New 的是Utf8 String,这里取出的应该还是[0xD6 0xD0]
×第16行从上面new的String中按GBK取得Byte数组, 这……不太确定,可能还是[0xD6 0xD0]?内存存储的编码应该是不变的?
×第19行从上面new的String中按ISO8859取得Byte数组, 这……同上吧? 但似乎有点儿问题,应该是不对,逻辑上如果getBytes都一样,那为啥要参数指定字符集呢?
第22行用[0xD6 0xD0]以ISO8859字符集new一个String,打印这个String,这里可能会乱码, 要看[0xD6 0xD0]ISO8859中对应的字符。
×第25,28行,这……
第30行从上面new的String中按ISO8859取得Byte数组,这应该不会变,还是[0xD6 0xD0]
我只能回答成这样了,自我感觉比较风流倜傥,潇洒惆怅的可以先自己琢磨下, 实际的程序输出在这里↓
1 ======================================== 2 bufferGBK = 0xD6,0xD0 3 gbkString =new String bufferGBK GBK : 中 4 utf8String =new String bufferGBK utf8 : �� 5 utf8String getBytes utf-8 : 0xEF,0xBF,0xBD,0xEF,0xBF,0xBD 6 utf8String getBytes GBK : 0x3F,0x3F 7 utf8String getBytes ISO-8859-1 : 0x3F,0x3F 8 isoString =new String bufferGBK ISO-8859-1 : ÖÐ 9 isoString getBytes utf-8 : 0xC3,0x96,0xC3,0x9010 isoString getBytes GBK : 0x3F,0x3F11 isoString getBytes ISO-8859-1 : 0xD6,0xD012 ========================================
答案点这里
然后对着输出结果来理解下。
答案中的2,3行输出跟预期一样
第4行确实是“乱码”了,但为什么[0xD6 0xD0]会变成两个一样的字符��
第5行,byte数组不是之前的2个,而是6个元素,与0xD6 0xD0完全不同,是何原因?
第6,7行,byte数组是[0x3F 0x3F],为啥?
第8行,也是“乱码”了,ÖÐ, 但为什么又变成了两个不同的字符。。-_-||
第9行 byte数组4个元素,看起来不同。
第10行 byte数组[0x3f 0x3f]
第11行 确实还是[0xD6 0xD0]
实践检验真理,上面的实验表明,String在内存存储的实际内容与getBytes取得的内容,可能是存在转换关系的。某些字符集的情况下是不变的(ISO8859),而有些经过Byte 到 String 到 Byte 的转换后会发生变化,与创建时的byte数组不同。
经过一番上下求索之后。下面是我认为比较合理的解释。
答案中的2,3行输出跟预期一样
第4行,乱码因为[0xD6 0xD0]不是两个有效的Utf8字符集字符, Java将其转换处理为两个�,即utf8String中的内容即为“��”
第5行此时取得Byte数组为对应Utf8 中两个�字符的字符编码,即在UTF8 字符集中� 的编码为[0xEF,0xBF,0xBD]
第6行取得的Byte数组为,字符�对应在GBK字符集中的字符编码,该字符应该未包含,被转换为 0x3F 即 ? 字符
第7行,同上
第8行,并不是乱码,Ö 和 Ð 确实是ISO8859字符集中包含的字符,对应的编码为[0xD6 0xD0],在GBK中为字符 “中” ,在 ISO8859中为两个字符 “Ö” 和 “Д,isoString内容为“ÖД
第9行,取得isoString在utf8 编码集中对应 Ö 和 Ð 字符的编码数组, 即 [0xC3,0x96] =Ö [0xC3,0x90] = Ð。
第10行,取得isoString在GBK编码其中对应的Ö 和 Ð 字符的编码数组,因为GBK未包含这两个字符,于是被转换为“??”后取得编码 即 [0x3F 0x3F]
第10行,取得isoString在ISO8859中对应的Ö 和 Ð 字符的编码数组,即为[0xD6 0xD0],因此不变。
总结及推论:
另:字符是抽象的,具体存储肯定要定义编码,Java规范定义的是“外部”的编码的表现和工作方式,内部存储可以自行实现,目前实际使用似乎是UTF16.
这一次的节点更新覆盖了韩国、新加坡、日本、香港、欧洲、加拿大、美国等地区,最高速度可达18.4 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
这一次的节点更新覆盖了新加坡、加拿大、香港、美国、欧洲、日本、韩国等地区,最高速度可达21.1 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
摘要: 本篇文章给大家谈谈宠物领养协议具有法律效应吗为什么还要签字,以及宠物领养协议需要身份证复印件吗对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。本文目录一览:1、狗给其他人..
摘要: 本篇文章给大家谈谈我所在的城市有一家动物医院英文作文怎么写,以及我所在的城市有一家动物医院英文改为一船疑问句对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。本文目录一览:..
摘要: 本篇文章给大家谈谈和田哪里有宠物店,以及和田卖宠物的地方对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。本文目录一览:1、和田哪里有卖仓鼠的么2、... 本篇文
这一次的节点更新覆盖了日本、新加坡、韩国、欧洲、香港、加拿大、美国等地区,最高速度可达21.7 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
这一次的节点更新覆盖了加拿大、韩国、新加坡、美国、日本、香港、欧洲等地区,最高速度可达18.2 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
摘要: 大家好,今天小编关注到一个比较有意思的话题,就是关于宠物粮食品牌都有什么牌子好的问题,于是小编就整理了3个相关介绍宠物粮食品牌都有什么牌子好的解答,让我们一起看看吧。鹦鹉粮食哪个品
这一次的节点更新覆盖了加拿大、日本、香港、韩国、美国、新加坡、欧洲等地区,最高速度可达22.7 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
这一次的节点更新覆盖了新加坡、香港、加拿大、美国、日本、韩国、欧洲等地区,最高速度可达19.6 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。