从Python编码说开去

Python脚本也就是.py文件使用unicode编码作为脚本编码,编码格式是UTF8。

Unicode编码: 为世界上所有的文字或字符一个编码。这个编码在Unicode中叫做代码点(code point)。一个代码点通常表示为“U+FFFF”的形式。 所有代码点的集合,即Unicode字符集叫做UCS(Universal Character Set)。UCS-2 是UCS code in 2 octets,即用两个字节表示的UCS,其表示范围为:U+0000 ~ U+FFFF。为了表示更多字符还有UCS-4,即用4个字节表示的UCS,其表示范围为:U+00000000 ~ U+7FFFFFFF。UCS-4中U+00000000 ~ U+0000FFFF与UCS-2是重叠的,UCS-2是UCS-4的一个子集。

代码点是Unicode字符的内码,但如何存储这个代码点或者说如何存储这个内码呢?是直接存储这个代码点(内码)的值吗?目前有多种格式。

首先解释一下大端(Big Endian)和小端(Little Endian)。 这个概念是源于中央处理器CPU对多字节数据(如,int 4字节,char 2字节等)的处理方式(存储和传输)。一种是多字节数据的低位字节可以存储于内存的低位地址,高位字节依序存储于高位内存地址 - Little Endian(高位字节存储于高位地址);另一种则相反 -  Big Endian(高位字节存储与低位地址)。如xe8af这个字符,高位字节是e8(11101000) 地位字节是af(10111111),存储于内存地址为0x00EFC77A和0x00EFC77B两个字节,如下所示:

Big Endian

0x00EFC77A     0x00EFC77B

11101000              10111111

--------------------------------------------

Little Endian

0x00EFC77A     0x00EFC77B

  10111111              11101000

多字节编码的字符在内存/文件中存储时存在大小端的问题。

Unicode编码的存储方式有:UTF16/UTF32/UTF8 三种格式

UTF16:
UTF16直接存储UCS-2内码值和UCS-2是完全对应的,是一种多字节(2字节)编码。由于字节序的缘故,UTF-16包括三种:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。

UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark)的字符来表明文件是Big Endian还是Little Endian。BOM为U+FEFF这个字符。其实BOM是个小聪明的想法。由于UCS-2没有定义U+FFFE,因此只要出现 FF FE 或者 FE FF 这样的字节序列,就可以认为它是U+FEFF,并且可以判断出是Big Endian还是Little Endian。

UTF32:

类似于UCS-2 和UTF16的情况,只是字符用4个字节表示 和UCS-4完全对应,也存在Big Endian和Little Endian的问题。

UTF-8:

UTF-16和UTF-32的一个缺点就是它们固定使用两个或四个字节,很多字符编码中会有多余的00,导致传输效率降低。而RFC3629定义的UTF-8则解决了这个问题。UTF-8用1~4个字节来表示代码点,并且定义了每个字节的格式特征,因此是一种单字节编码方式,不存在Big Endian和Little Endian的问题。存储一个UTF-8字符时,需要将这个字符的Unicode内码,编码成字节数组,然后需要按照数组的顺序,一个一个字节写入,不用考虑字节序问题。其实本质是Big Endian。

 

表示方式如下:

UCS-2 (UCS-4)位序列第一字节第二字节第三字节第四字节
U+0000 .. U+007F00000000-0xxxxxxx0xxxxxxx   
U+0080 .. U+07FF00000xxx-xxyyyyyy110xxxxx10yyyyyy  
U+0800 .. U+FFFFxxxxyyyy-yyzzzzzz1110xxxx10yyyyyy10zzzzzz 
U+10000..U+1FFFFF00000000-000wwwxx-
xxxxyyyy-yyzzzzzzz
11110www10xxxxxx10yyyyyy10zzzzzz

按照UTF-8标准: 
(1)所有以0开始的字节,都与原来的ASCII码兼容,也就是说,0xxxxxxx不需要额外转换,就是我们平时用的ASCII码。 
(2)所有以10开始的字节,都不是每个UNICODE的第一个字节,都是紧跟着前一位。例如:10110101,这个字节不可以单独解析,必须通过前一个字节来解析,如果前一个也是10开头,就继续前嗍。 
(3)所有以11开始的字节,都表示是UNICODE的第一个字节,而且后面紧跟着若干个以10开头的字节。如果是110xxxxx(就是最左边的0的左边有2个1),代表后面还有1个10xxxxxx;如果是1110xxxx(就是最左边的0的左边有3个1),代表后面还有2个10xxxxxx;以此类推。 很明显,以11开头的,最左边的0左边有多少个1,那这个UCS的UTF-8的表示长度就有多少个字节。

注意:在微软window操作系统中,会给utf-8文件添加BOM【EF BB BF】(虽然不需要这么做),这并不是说明UTF-8需要字节序,而是仅仅表名该文件是utf-8编码的文件。

 

 

Reference: 

https://blog.csdn.net/imxiangzi/article/details/77371228

https://blog.csdn.net/yo746862873/article/details/51780894

            

有关ANSI, ANSI 不是一种编码方式,而是使用字符编码的约定。只有windows在使用。ANSI的全称是 America National Standard Institute(美国国家标准协会)。微软在处理字符编码时收集了各个国家定义个各种字符编码集,如中国的GBK,台湾的Big5,韩国的EUC-KR,日本的Shift_JIS等等。每种编码在系统中定义了一个代码页(Windows code page) 来表示,每个代码页被赋予一个唯一的编码,如GBK 的code page 是936。通过设置Windows系统的Region and Language选项来指定系统当前使用的代码页。当Windows 程序在处理编码的时候可以通过当前活动代码页(active code page)调用相应的字符编码。这是微软解决系统本地化的方案。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值