记事本 BOM 之 “联通” "联" “联想” 为什么有的显示不正常
2017-07-14 13:40
169 查看
作者:TwinsForChina
链接:https://www.zhihu.com/question/25367290/answer/138972490
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我们来做个测试
1. 用Windows记事本程序创建3个文件,分别输入“联想”,“联通”,“联”,然后分别保存
2. 再次打开
你可以看到什么了?是不是“联通”会消失了。一般我们在记事本里面写中文,保存的时候,默认应该是ansi格式的。输入“联通”之后,再次打开,记事本根据utf8的特征,误以为此文本是utf8的格式了。然后后面的事情便是一错再错了。如果是以utf8或者unicode的格式保存,再次打开,会是什么结果了?呵呵,自己看吧
我们来细说下吧
先看这个, UTF-8编码采用1-3个字节对字符进行编码,编码字节数与字符的Unicode编码值有严格的对应关系,让我们看下UTF-8编码和Unicode的对应关系吧。
Unicode编码值 UTF-8编码结构
\u0001 - \u007E 0XXXXXXX
\u0080 - \u07FF 和 \u0000 110XXXXX 10XXXXXX
\u0800 - \uFFFF 和1110XXXX 10XXXXXX 10XXXXXX
“联通”这两个字符的GBK编码值是“C1 AA CD A8",GBK编码方式使用两个字节对一个字符进行编码,因此以GBK编码方式存放的录有“联通”两个字符的文件的大小为四个字节。接下来分别观察“联通”这两个字符GBK编码值的二进制形式,你有发现有趣的事。
联 GBK 十六进制:C1 AA 二进制:1100 0001,1010 1010
通 GBK 十六进制:CD A8 二进制:1100 1101,1010 1000
请注意上面二进制数据的加粗部分,你想到了什么?对,它们和UTF-8编码结构中的补充位完全一致,UTF-8编码的补充位使得编码值更有规律,而记事本刚好凭借这个特征区分UTF-8编码的文件。存有“联通”两个字符的文件的所有数据都符合这个特征,就是这样,记事本彻底的将文件误认为UTF-8编码的文件。
将错就错,让我们来看看这个错误是怎样收场的。如果把“联通”的GBK编码值当作UTF-8编码值,那文件就成为一个写有数据“C1 AA CD A8”并以UTF-8编码的文件,当使用记事本再次打开的时候会看到什么呢?只要将UTF-8编码转换成Unicode编码就知道了(为啥要转成unicode咧,因为utf8是unicode的一种实现方式,只有unicode才有二进制和字符的对应关系)。
转换方法:让我们把第一个字节的110和第二个字节的10去掉,我们就得到了"00001 101010",再把各位对齐,补上前导的0,就得到了"0000 0000 0110 1010"。UTF-8编码“C1 AA CD A8”转换成Unicode编码后,编码值为“6A 00 68 03”。
0x006A这个Unicode编码值位于\u0001 - \u007E之间,若要转换为UTF-8编码,显然只能用一个字节进行编码,因此“联”的GBK编码“C1 AA”虽然特征上貌似UTF-8编码,但它却不对应任何一个UTF-8编码。接着看0x0368这个Unicode编码值,这个值对应了字符“ͨ”,这也正是我们将在记事本中看到的内容。或许你会说我看到的是一个黑色矩形啊,这只是字体的原因,你将字体改为宋体或者其他字体,看到的就是字符“ͨ”。
对于中文字符,UTF-8编码要用三个字节进行编码,因此,如果你使用记事本录入“联通”,然后选择以UTF-8编码方式保存的话,文件大小应为9个字节(包含三个字节的开头数据),而同样的文件GBK编码却是4个字节。最后附上“联通”的GBK、UTF-8、Unicode编码值,以及记事本的错误思维。
联通 GBK C1 AA CD A8 UTF-8 E8 81 94 E9 80 9A Unicode 54 80 1A 90
联通 GBK C1 AA CD A8 UTF-8 C1 AA CD A8 Unicode 6A 00 68 03 (将GBK值误认为UTF-8值的结果)
链接:https://www.zhihu.com/question/25367290/answer/138972490
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我们来做个测试
1. 用Windows记事本程序创建3个文件,分别输入“联想”,“联通”,“联”,然后分别保存
2. 再次打开
你可以看到什么了?是不是“联通”会消失了。一般我们在记事本里面写中文,保存的时候,默认应该是ansi格式的。输入“联通”之后,再次打开,记事本根据utf8的特征,误以为此文本是utf8的格式了。然后后面的事情便是一错再错了。如果是以utf8或者unicode的格式保存,再次打开,会是什么结果了?呵呵,自己看吧
我们来细说下吧
先看这个, UTF-8编码采用1-3个字节对字符进行编码,编码字节数与字符的Unicode编码值有严格的对应关系,让我们看下UTF-8编码和Unicode的对应关系吧。
Unicode编码值 UTF-8编码结构
\u0001 - \u007E 0XXXXXXX
\u0080 - \u07FF 和 \u0000 110XXXXX 10XXXXXX
\u0800 - \uFFFF 和1110XXXX 10XXXXXX 10XXXXXX
“联通”这两个字符的GBK编码值是“C1 AA CD A8",GBK编码方式使用两个字节对一个字符进行编码,因此以GBK编码方式存放的录有“联通”两个字符的文件的大小为四个字节。接下来分别观察“联通”这两个字符GBK编码值的二进制形式,你有发现有趣的事。
联 GBK 十六进制:C1 AA 二进制:1100 0001,1010 1010
通 GBK 十六进制:CD A8 二进制:1100 1101,1010 1000
请注意上面二进制数据的加粗部分,你想到了什么?对,它们和UTF-8编码结构中的补充位完全一致,UTF-8编码的补充位使得编码值更有规律,而记事本刚好凭借这个特征区分UTF-8编码的文件。存有“联通”两个字符的文件的所有数据都符合这个特征,就是这样,记事本彻底的将文件误认为UTF-8编码的文件。
将错就错,让我们来看看这个错误是怎样收场的。如果把“联通”的GBK编码值当作UTF-8编码值,那文件就成为一个写有数据“C1 AA CD A8”并以UTF-8编码的文件,当使用记事本再次打开的时候会看到什么呢?只要将UTF-8编码转换成Unicode编码就知道了(为啥要转成unicode咧,因为utf8是unicode的一种实现方式,只有unicode才有二进制和字符的对应关系)。
转换方法:让我们把第一个字节的110和第二个字节的10去掉,我们就得到了"00001 101010",再把各位对齐,补上前导的0,就得到了"0000 0000 0110 1010"。UTF-8编码“C1 AA CD A8”转换成Unicode编码后,编码值为“6A 00 68 03”。
0x006A这个Unicode编码值位于\u0001 - \u007E之间,若要转换为UTF-8编码,显然只能用一个字节进行编码,因此“联”的GBK编码“C1 AA”虽然特征上貌似UTF-8编码,但它却不对应任何一个UTF-8编码。接着看0x0368这个Unicode编码值,这个值对应了字符“ͨ”,这也正是我们将在记事本中看到的内容。或许你会说我看到的是一个黑色矩形啊,这只是字体的原因,你将字体改为宋体或者其他字体,看到的就是字符“ͨ”。
对于中文字符,UTF-8编码要用三个字节进行编码,因此,如果你使用记事本录入“联通”,然后选择以UTF-8编码方式保存的话,文件大小应为9个字节(包含三个字节的开头数据),而同样的文件GBK编码却是4个字节。最后附上“联通”的GBK、UTF-8、Unicode编码值,以及记事本的错误思维。
联通 GBK C1 AA CD A8 UTF-8 E8 81 94 E9 80 9A Unicode 54 80 1A 90
联通 GBK C1 AA CD A8 UTF-8 C1 AA CD A8 Unicode 6A 00 68 03 (将GBK值误认为UTF-8值的结果)
相关文章推荐
- 【解决】为什么网页都完全显示出来且打开了,状态栏左下角还显示"正在打开网页..."?
- "联通"保存不能显示的解释
- 【Unity&NGUI】为什么把NGUI的UI制作为预制体,再生成到新场景,UI无法正常在Game视图显示
- php图片验证码,为什么非要加上ob_clean();这句话才能正常显示呢?
- 为什么matplotlib显示opencv图像不正常
- 为什么VMWare12虚拟机无法正常上网,网络连接显示网络未连接拔出故障
- Struts 2 type="stream" 中文filename如何正常显示
- 为什么连接图片不能正常显示
- 为什么用Android Volley时返回的中文是乱码,而postman却显示正常
- Ext.form 表单为什么第二次就不正常显示
- Python读取windows下记事本保存的UTF-8格式的内容,首行数据显示不正常的解决办法
- 设定画板的大小并且不影响正常显示( d:DesignWidth="1300" d:DesignHeight="768")
- 如何打开记事本并显示指定内容 - 回复 "苦苦苦" 的问题
- Image image = Toolkit.getDefaultToolkit().getImage("picture/bg.jpg");// 这种图片加载方法为什么要 先最小化窗口然后才会显示
- 为什么img标签高度显示不正常?
- 记事本不能显示“联通”二字的原因
- 为什么用360浏览器打开网页显示不正常而其他浏览器都正常
- 为什么用Response.Write("dbcd")输出文本后,查看源码,显示出来的bdcd字符串在html代码的外面?— —服务器输出的缓存区
- iframe自适应父页面的大小,而没有滚动条,scrolling="no"后无法正常显示内容的问题
- 为什么我装完SQL Server 2000后,"SQL Server组"中没有项目,下一级显示为“无项目”