python中编码问题

编码是将存储在文件中的二进制数据以特定的格式显示的一种手段。不同的操作系统、不同的编辑环境,对于python进行文件操作带来了很大的挑战,总体表现在三方面:

1、操作系统对文件编码的影响

2、python编辑环境对python编码的影响

3、文件内容对编码的要求

 

扩展来说:

1、不同操作系统,生成的文件的默认编码不同。

Win10有几个版本(截止2018年)?

根据微软今天的正式公布,Win10共划分为7个版本,具体如下:

- Windows 10家庭版(Windows 10 Home)

- Windows 10专业版(Windows 10 Pro)

- Windows 10企业版(Windows 10 Enterprise)

- Windows 10教育版(Windows 10 Education)

- Windows 10移动版(Windows 10 Mobile)

- Windows 10企业移动版(Windows 10 Mobile Enterprise)

- Windows 10 IoT Core(主要针对物联网设备)

以txt文件的默认编码为例,不同语言、不同版本的操作系统其生成的txt文件默认编码不同:(以下以中文为例说明)

- Windows 10家庭版(Windows 10 Home) :txt默认编码为:utf-8

- Windows 10专业版(Windows 10 Pro):txt默认编码为:utf-8

- Windows 10教育版(Windows 10 Education):txt默认编码为:ANSI

(只测试了这三个版本)

2、python编辑环境对python编码的影响

不同编辑环境,其默认的编码也不同,以pycharm为例,其默认编码位GBK,所以如果print中的内容为GBK不能识别的,则会出现错误;如果在使用pycharm读文件时,没有明确指定encoding为和打开一致的编码格式,会提示编码出错。

可以对编辑环境的默认编码进行设置,以pycharm为例,设置方式如下:

python中编码问题

如果你是家庭版的win10系统,那么上述设置会节约你很多因为编码不一致而导致的时间浪费。(utf-8推荐)

3、文件内容对编码的要求

不同语言,其要正常显示,需要使用对应的编码,如果编码不一致,会出现乱码。常见编码简要说明如下:

常见编码方式:Unicode、ASCII、GBK、GB2312等

(1)ASCII:能表示128个字符,其中包括英文字符、阿拉伯数字、西文字符以及32个控制字符。它用一个字节来表示具体的字符,但它只用后7位来表示字符(2^7=128),最前面的一位统一规定为0。

扩展ASCII码(即ANSI编码):原本的ASCII码对于英文语言的国家是够用了,但是欧洲国家的一些语言会有拼音,这时7个字节就不够用了。因此一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。 这样一来,这些欧洲国家使 用的编码体系,可以表示最多256个符号。但这时问题也出现了:不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码 中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0—127表示的符号是一样的,不一样的只是128—255的这一段。这个问题就直接促使了Unicode编码的产生。但是正因为Unicode包含了所有的字符,而有些国家的字符用一个字节便可以表示,而有些国家的字符要用多个字节才能表示出来。

(2)unicode:世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。而Unicode就是这样一种编码:它包含了世界上所有的符号,并且每一个符号都是独一无二的。比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字“严”。具体的符号对应表,可以查询unicode.org,或者专门的汉字对应表 。很多人都说Unicode编码,但其实Unicode是一个符号集(世界上所有符号的符号集),而不是一种新的编码方式。 但是正因为Unicode包含了所有的字符,而有些国家的字符用一个字节便可以表示,而有些国家的字符要用多个字节才能表示出来。即产生了两个问题:第一,如果有两个字节的数据,那计算机怎么知道这两个字节是表示一个汉字呢?还是表示两个英文字母呢?第二,因为不同字符需要的存储长度不一样,那么如果Unicode规定用2个字节存储字符,那么英文字符存储时前面1个字节都是0,这就大大浪费了存储空间。 上面两个问题造成的结果是:1)出现了unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示unicode。2)unicode在很长一段时间内无法推广,直到互联网的出现。

(3)UTF-8:解决国际上字符的一种多字节编码。英文使用8位(即一个字节),中文使用24位(三个字节)来编码。互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种unicode的实现方式。其他实现方式还包括UTF-16和UTF-32,不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一。 UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。UTF-8的编码规则很简单,只有两条: 1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。 2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

(4)GBK/GB2312/GB18030 GBK和GB2312都是针对汉字的编码。1、GBK和GB2312 都是16位的。 2、GBK(支持1万多个汉字编码)支持简体中文和繁体中文,而GB2312只支持简体中文(只支持六千多个汉字)的编码,GBK里面包含了GB2312,用GBK比较多。 3、GB18030是32位的,它支持简体中文、繁体中文 藏文、蒙文、*文等主要的少数民族文字,包含GBK和GB2312。 4、从GB2312(1980年)、GBK(1995年)到GB18030(2000年),这些编码方法是向下兼容的。

补充内容:

1、NUNICODE下UTF-8、UTF-16及UTF-32。

UTF(UCS Transformation Format)是面向网络传输的一系列标准。UTF-8:每次8个位传输数据;UTF-16:每次16个位传输数据。例如:在UTF-8中,0-127号的字符用1个字节来表示,使用与ASCII相同的编码(兼容);128号及以上的字符才用2个、3个(如汉字)或者4个字节来表示。UTF-8被称作可变长度编码。因为其解决了UNICODE不便于传输的问题,于是得到了广泛使用。

2、低字节序与高字节序和BOM

在UTF-8中有带BOM的和不带BOM。BOM(BOM——Byte Order Mark,就是字节序标记),是在网络里传递信息时有一个很重要问题,就是对于数据高低位的解读方式,即字节序问题。一些计算机是采用低位字节被存在前面的方式,称之为低字节序(Little Endian),例如Intel架构的微处理器;而另一些是采用高位字节被存在前面的方式,称之为高字节序(Big Endian),例如Motorola架构的微处理器。在网络中数据交换时,为了核对双方对于高低位的规则是否是一致的,采用了一种很简便的方法——文本流前添加BOM(Byte Order Mark,字节顺序标记),就是在文本流的开始时添加一个标志符来表示该文本的字节序。具体规则是如果该文本是高字节序,BOM就为FEFF,反之,则为FFFE。

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE“的UTF-8编码EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。