字符编码附属乱码篇

来源:互联网 发布:淘宝店铺号怎么搜索 编辑:程序博客网 时间:2024/05/17 08:28

在上一篇中,字符编码的基本概念,各种常见问题都解决了,这儿分析如下几个编码问题。windows下记事本中“联通”bug,显示乱码?�的问题。大端小端问题。

还是先从一个故事开始吧。

Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。据估计,先后几次有11000余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。这个其实讽刺当时英国和法国之间持续的冲突。Danny Cohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。

在桌面上新建一个记事本文件,在里面输入联通两个字,然后保存,关闭,再打开,“联通”二字变成了��ͨ有人说这就是移动比联通强盛的原因。我也是醉了。“联通”的内码是0xC1(1100 0001), 0xAA(1010 1010),0xCD(1100 1101),0xA8(1010 1000)这两个字的起始部分的是"110"和"10",正好与UTF8规则里的两字节模板是一致的,于是再次打开记事本时,记事本就误认为这是一个UTF8编码的文件……当文档中所有字符(假设编码:AABB)都在(C0≤AA≤DF,80≤BB≤BF)这个范围的时候都会遇到这个问题……而且像一丝,一两,一些,一位,一位女士,一俟,一偏,一元,一准,一力,一匹,一十,一千,一千元,一去,一双,也会出错的。

根源还是windows弄混了uTF编码和gb编码的原因。

Windows记事本保存方法
四个选项:ANSI,Unicode,Unicode big endian 和 UTF-8。
1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。
2)Unicode编码指的是UCS-2编码方式,即直接用两个字节存入字符的Unicode码。这个选项用的little endian格式。
3)Unicode big endian编码与上一个选项相对应。
4)UTF-8编码,

在最开始的故事里说到了大小端。假设一个数字是int型,它需要32位存储,用十六进制写为0x12 34 56 78.那么这几个数字应该是12在一个字节,34在一个字节,56 78各在一个字节。那么问题来了。内存地址是从小到大的,该怎么放呢,12在高位上,权重大,假设在四个字节中存储。这就有顺序和逆序了。如图


小端呢,高位在后面便于计算,比如4000字节值乘以1,4001乘以256,这样顺序很好算。而大端呢,读取字符方便,从前往后12 34 56 78比起小端的 78 56 34 12顺多了吧。

大小端,从低地址往高地址走,按着顺序读下去的为大端。
一般操作系统都是小端,而通讯协议是大端的。常见CPU的字节序
Big Endian : PowerPC、IBM、Sun
Little Endian : x86、DEC。

windows下记事本为了方便区分各种编码,用了BOM。BOM最初设计是为了解决诸如UTF16两个字节大小端的问题,也就是先存储高位还是低位。或者在网络传输协议中先传高位还是低位。然而微软在记事本只用也利用它来辨别编码种类问题。所以就多了一种问你,容易出现最初吧联通搞错的故事了。

BOM byte order mark。Unicode的字节顺序 标记。UTF16为U+FEFF。看大小端,大端为FEFF,小端为FFFE。
UTF-8 不需要 BOM,尽管 Unicode 标准允许在 UTF-8 中使用 BOM。所以不含 BOM 的 UTF-8 才是标准形式,在 UTF-8 文件中放置 BOM 主要是微软的习惯,把带有 BOM 的小端序 UTF-16 称作「Unicode」而又不详细说明,这也是微软的习惯)。BOM(byte order mark)是为 UTF-16 和 UTF-32 准备的,用于标记字节序(byte order)。微软在 UTF-8 中使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码明确区分开,但这样的文件在 Windows 之外的操作系统里会带来问题。

文件中加了编码顺序字符 FEFF,如果FF开头为小端,FE为大端。EF BB BF代表UTF-8编码。

乱码问题
当程序用特定字符编码解析字节流的时候,一旦遇到无法解析的字节流时,就会用symbol或者?�来替代。因此,一旦最终解析得到的文本包含这样的字符,而你又无法得到原始字节流的时候,说明正确的信息已经彻底丢失了,尝试任何字符编码都无法从这样的字符文本中还原出正确的信息来。

?在ascii码中为3F,因此当你传FF接收到字节为3F说明你的数据已经失真了。

�是一种替代符号unicode编码为U+FFFD。65533表示这不是合法unicode编码

0 0
原创粉丝点击