1、字符编码
字符编码(英语:Character encoding)也称字集码,是把字符集中的字符编码为指定集合中某一对象(例如:比特模式、自然数序列、8位组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。常见的例子包括将拉丁字母表编码成摩斯电码和ASCII。其中,ASCII将字母、数字和其它符号编号,并用7比特的二进制来表示这个整数。
1)ASCII
美国(国家)信息交换标准(代)码,一种使用7个或8个二进制位进行编码的方案,最多可以给256个字符(包括字母、数字、标点符号、控制字符及其他符号)分配(或指定)数值。
ASCII码于1961年提出,用于在不同计算机硬件和软件系统中实现数据传输标准化,在大多数的小型机和全部的个人计算机都使用此码。ASCII码划分为两个集合:128个字符的标准ASCII码和附加的128个字符的扩充和ASCII码。比较EBCDIC。其中95个字符可以显示。另外33个不可以显示。 标准ASCII码为7位,扩充为8位。
目前使用最广泛的西文字符集及其编码是 ASCII 字符集和 ASCII 码( ASCII 是 American Standard Code for Information Interchange 的缩写),它同时也被国际标准化组织( International Organization for Standardization, ISO )批准为国际标准。
2)GB2312
GB2312 也是ANSI编码里的一种,对ANSI编码最初始的ASCII编码进行扩充,为了满足国内在计算机中使用汉字的需要,中国国家标准总局发布了一系列的汉字字符集国家标准编码,统称为GB码,或国标码。其中最有影响的是于1980年发布的《信息交换用汉字编码字符集 基本集》,标准号为GB 2312-1980,因其使用非常普遍,也常被通称为国标码。GB2312编码通行于我国内地;新加坡等地也采用此编码。几乎所有的中文系统和国际化的软件都支持GB 2312。
3)GBK
GBK即汉字内码扩展规范,K为扩展的汉语拼音中“扩”字的声母。英文全称Chinese Internal Code Specification。GBK编码标准兼容GB2312,共收录汉字21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库。GB2312码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集——基本集》,1980年由国家标准总局发布。基本集共收入汉字6763个和非汉字图形字符682个,通行于中国大陆。新加坡等地也使用此编码。GBK是对GB2312-80的扩展,也就是CP936字码表 (Code Page 936)的扩展(之前CP936和GB 2312-80一模一样)。
4)Unicode
如上ANSI编码条例中所述,世界上存在着多种编码方式,在ANSi编码下,同一个编码值,在不同的编码体系里代表着不同的字。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码,可能最终显示的是中文,也可能显示的是日文。在ANSI编码体系下,要想打开一个文本文件,不但要知道它的编码方式,还要安装有对应编码表,否则就可能无法读取或出现乱码。为什么电子邮件和网页都经常会出现乱码,就是因为信息的提供者可能是日文的ANSI编码体系和信息的读取者可能是中文的编码体系,他们对同一个二进制编码值进行显示,采用了不同的编码,导致乱码。这个问题促使了unicode码的诞生。
如果有一种编码,将世界上所有的符号都纳入其中,无论是英文、日文、还是中文等,大家都使用这个编码表,就不会出现编码不匹配现象。每个符号对应一个唯一的编码,乱码问题就不存在了。这就是Unicode编码。
Unicode当然是一个很大的集合,现在的规模可以容纳100多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,“汉”这个字的Unicode编码是U+6C49。
Unicode固然统一了编码方式,但是它的效率不高,比如UCS-4(Unicode的标准之一)规定用4个字节存储一个符号,那么每个英文字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。
5)UTF-8
为了提高Unicode的编码效率,于是就出现了UTF-8编码。UTF-8可以根据不同的符号自动选择编码的长短。比如英文字母可以只用1个字节就够了。
UTF-8的编码是这样得出来的,以”汉”这个字为例:
“汉”字的Unicode编码是U+00006C49,然后把U+00006C49通过UTF-8编码器进行编码,最后输出的UTF-8编码是E6B189。
2、.py文件编码问题
报错信息:Non-ASCII character '\xe4' in file demo.py on line 1, but no encoding declared;
问题原因:一般报这个错误时,我们使用print sys.getdefaultencoding()
输出一下Python默认编码,一般这种情况默认编码都是ASCII,而ASCII不能识别\xe4
,所以会报错。根据上面字符编码可知,ASCII 编码是不能表示汉字中文的。
解决方法:.py
文件头加上# encoding:utf-8
,存储.py
文件时以utf-8
编码,就不会乱码了。
示例代码如下:
# encoding:utf-8
import sys
print sys.getdefaultencoding()
s = "中文乱码问题解决"
print repr(s)
注意:编码声明注释写成# -*- coding: utf-8 -*-
也可以,只要满足正则表达式^[ \t\v]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)
。
3、Python IDE中正常面CMD中乱码
CMD 下进入 python 交互模式输出中文是正常的,在Python IDE下输出中文也是正常的,但在CMD中,使用Python file.py
方式运行就乱码。
问题原因:这种情况下,在 CMD 或者 Python IDE 中打印字符的时候已经和文件编码方式无关了,问题在于输出环境 CMD 或者 Python IDE的编码方式。
CMD 的编码命令是 chcp
,返回 936
,936
代表 GBK
编码。.py
文件存储和编码声明都是utf-8
,但CMD 显示编码是 GBK
。而将中文的utf-8
编码字符串强制转换为 GBK
就会乱码。
解决方法:
1).py
文件和编码声明为 GBK,比较麻烦不推荐此方法
例如:
# encoding:gbk
s = "中文乱码问题解决"
print s
print repr(s)
2)在中文前面加上个小写u
标记,后面的中文就用 unicode
存储
# encoding:utf-8
s = u"中文乱码问题解决"
print s
print repr(s)
CMD 下使用Python file.py
就可以打印 unicode
字符了。
3)中文强制转换为GBK或unicode编码
强制转换为unicode
编码,在 Python 中编码是可以互相转换的,如从utf-8
转换为gbk
,不同编码之间不能直接转换,需要先转成unicode
字符集,在转换成其它编码,通过上面字符编码的介绍可知unicode
是一种字符集,不属于编码,而utf-8
是具体实现unicode
的一种编码。utf-8
转换为unicode
是一种解码过程,通过decode
可从utf-8
解码成unicode
。
例如,
# encoding:utf-8
s = "中文乱码问题解决"
u = s.decode('utf-8')
print u
print type(u)
print repr(u)
强制转换为gbk
编码,从utf-8
转换为unicode
后,从unicode
是编码的过程,通过encode
实现。
例如,
# encoding:utf-8
s = "中文乱码问题解决"
u = s.decode('utf-8')
g = u.encode('gbk')
print g
print type(g)
print repr(g)
注意:Windows CMD 窗口下不支持utf-8
,显示中文必须转换为gbk
或者unicode
,而 Python IDE 中这三种编码都支持。中文乱码的出现都是由于编码不一致导致的,存储的是用utf-8
,打印输出用gbk
就会乱码了,所有要保证不乱码尽量保持统一,建议使用unicode
。
4、decode() 解码
其它编码变成unicode
叫解码,decode()
方法可以实现解码,第一个参数为被解码的字符串原始编码格式,
例如,
# encoding:utf-8
s = "中文"
u = s.decode('utf-8')
#不能指定错编码格式,否则会报错。
#u = s.decode('gbk')
print u
print repr(u)
注意:有些情况下,两个中文字符判断是相等的,但于换了运行环境,导制两个字符串编码不一致,可能出现意外的情况下,需要注意一下。
5、encode() 编码
不能直接从utf-8
转换为gbk
,需要经过unicode
中间转换,被编码的原始字符串一定要为unicode
,否则会报错。
例如,
# encoding:utf-8
s = "中文乱码问题解决"
#直接执行s.encode('gbk')会报错,需要执行.decode('utf-8')转换成unicode后,在执行encode()
u = s.decode('utf-8')
g = u.encode('gbk')
print g
print type(g)
print repr(g)
6、raw_input()
raw_input
作用是获取用户输入,获取到的用户输入和当前运行环境编码有关,如 CMD 下默认编码是 gbk
,则输入的汉字就是以gbk
编码,而不管.py
文件编码格式和编码声明。
例如,
# encoding:utf-8
s = raw_input(u"输入中文字符: ")
print s
print type(s)
print repr(s)
注意:文件存储为utf-8
格式,编码声明为utf-8
,# encoding:utf-8
,出现汉字的地方前面加 u
,不同编码之间不能直接转换,要先转成unicode
,然后从unicode
转成其它编码。