ASCII:ASCII码即美国标准信息交换码(American Standard Code for Information Interchange)。因为计算机内部全部信息最终都是一个二进制值,而每个二进制位(bit)有0
和1
两种状态,所以八个二进制位就能够组合出256种状态,这被称为一个字节(byte)。标准ASCII 码一共规定了128个字符的编码,这是由于只使用了后面七位,最前面的一位统一规定为0。以后IBM制定了128个扩充字符,这些字符并不是标准的ASCII码,而是用来表示框线、音标和其它欧洲非英语系的字母。html
英语用128个符号编码就够了,可是用来表示其余语言,128个符号是不够的,并且不一样的国家使用不一样的字母,有的国家使用的字符也远远超过256个,显然ASCII已经没法解决问题了。那么有没有一种统一且惟一的编码方式呢?答案就是Unicode。浏览器
Unicode:Unicode是计算机科学领域里的一项业界标准,Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每一个字符设定了统一而且惟一的二进制编码,以知足跨语言、跨平台进行文本转换、处理的要求。网络
可是Unicode也是有问题的,好比“中”字的Unicode编码是十六进制的4E2D,即二进制的100111000101101占15位,也就是说表示这个符号至少须要两个字节,那么怎么知道这两个字节是表示一个字符而不是分别表示两个字符呢?也就是如何区分Unicode和ASCII?ide
UTF-8:UTF是“Unicode Transformation Format”的缩写,能够翻译成Unicode字符集转换格式。UTF-8 就是在互联网上使用最广的一种Unicode的实现方式,其余实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示)。UTF-8最大的一个特色,就是它是一种变长的编码方式。它可使用1~6个字节表示一个符号,根据不一样的符号而变化字节长度。对于某一个字符的UTF-8编码,若是只有一个字节则其最高二进制位为0;若是是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其他各字节均以10开头。编码
字节数 | UTF-8编码(二进制)spa
1 | 0xxxxxxx 操作系统
2 | 110xxxxx 10xxxxxx翻译
3 | 1110xxxx 10xxxxxx 10xxxxxx 3d
4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx code
5 | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6 | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
很明显对于“中”字使用UTF-8编码须要使用三个字节,所以从“中”字的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就获得了“中”字的UTF-8编码,结果为:11100100 10111000 10101101,即十六进制的E4B8AD。
Python中的编码问题困扰了我挺久的,尤为是Python2和Python3中还有区别,不过这里我只讨论Python3中的编码问题。
Python3最重要的新特性大概要算是对文本和二进制数据做了更为清晰的区分,文本老是Unicode,由str类型表示,二进制数据则由bytes类型表示,而二者之间的转换由编码(encode)和解码(decode)实现。这里能够看一下Python的官方文档:
str.encode(encoding="utf-8", errors="strict")
Return an encoded version of the string as a bytes object. Default encoding is 'utf-8'. errors may be given to set a different error handling scheme. The default for errors is 'strict', meaning that encoding errors raise a UnicodeError. Other possible values are 'ignore', 'replace', 'xmlcharrefreplace
'
, 'backslashreplace'
and any other name registered via codecs.register_error(), see section Error Handlers. For a list of possible encodings, see section Stardard Encodings.
bytes.decode(encoding="utf-8", errors="strict")
Return a string decoded from the given bytes. Default encoding is 'utf-8'. errors may be given to set a different error handling scheme. The default for errors is 'strict', meaning that encoding errors raise a UnicodeError. Other possible values are 'ignore', 'replace' and any other name registered via codecs.register_error(), see section Error Handlers. For a list of possible encodings, see section Stardard Encodings.
能够看到str是没有decode方法的,由于自己就是Unicode编码的,而bytes是没有encode方法的,并且不管是encode仍是decode默认都是使用UTF-8编码的,固然咱们还可使用其余方式进行编码和解码,好比:
s = "博客园"
print(s.encode())
print(s.encode("utf-16"))
print(s.encode("gbk"))
# b'\xe5\x8d\x9a\xe5\xae\xa2\xe5\x9b\xad'
# b'\xff\xfeZS\xa2[\xedV'
# b'\xb2\xa9\xbf\xcd\xd4\xb0'
那么对于某个数据来讲,若是咱们不知道它的编码格式,要怎么办呢?在Python3中可使用chardet模块里的detect方法查看:
import chardet
print(chardet.detect(b'\xe5\x8d\x9a\xe5\xae\xa2\xe5\x9b\xad'))
print(chardet.detect(b'\xff\xfeZS\xa2[\xedV'))
{'encoding': 'utf-8', 'confidence': 0.87625, 'language': ''}
{'encoding': 'UTF-16', 'confidence': 1.0, 'language': ''}
detect方法会返回一个字典,包含编码方式、检测获得的几率和语言信息。可见,用chardet检测编码,使用简单,获取到编码后,再转换为str
,就能够方便后续处理。
首先新建一个文本文档“test.txt”,内容为:“博客园Blogs”,而后选择“另存为”,能够看到默认使用的是ANSI编码:
那么这个ANSI编码是什么呢?不一样的国家和地区制定了不一样的标准,由此产生了GB23十二、GBK、Big五、Shift_JIS等各自的编码标准。这些使用1至4个字节来表明一个字符的各类汉字延伸编码方式,称为ANSI编码。而在简体中文Windows操做系统中,ANSI编码就表明GBK编码。那么假如咱们使用了默认的ANSI编码即GBK编码,在读取文本的时候会出现什么状况呢?
with open("test.txt", 'r') as f:
print(f.read())
# 博客园Blogs
with open("test.txt", 'r', encoding="gbk") as f:
print(f.read())
# 博客园Blogs
with open("test.txt", 'r', encoding="utf-8") as f:
print(f.read())
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 0: invalid start byte
能够看到使用UTF-8编码打开的时候报错了,缘由是有没法解码的字符。那么若是咱们保存的时候使用UTF-8编码呢?
with open("test.txt", 'r') as f:
print(f.read())
# 锘垮崥瀹㈠洯Blogs
with open("test.txt", 'r', encoding="gbk") as f:
print(f.read())
# 锘垮崥瀹㈠洯Blogs
with open("test.txt", 'r', encoding="utf-8") as f:
print(f.read())
# 博客园Blogs
很明显看到在使用GBK编码时出现乱码了,缘由就是编码和解码的方式不一致,致使最终出现了乱码的状况。
URL即全球统一资源定位符(Uniform Resource Locator),通常来讲,URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其余文字和符号,这是由于网络标准RFC1738作出了规定。这意味着,若是URL中有汉字,就必须编码后使用。可是麻烦的是,RFC1738没有规定具体的编码方法,而是交给应用程序(浏览器)本身决定。
这里咱们能够任意打开一个网页,好比关于编码的百度百科,能够看到浏览器显示的连接没有什么问题:
复制一下,而后粘贴出来看一下:https://baike.baidu.com/item/%E7%BC%96%E7%A0%81/80092,能够看到“编码”两个字被浏览器自动编码成了“%E7%BC%96%E7%A0%81”。这里咱们须要知道的是“编”的UTF-8编码为:E7BC96,“码”的UTF-8编码为:E7A081,所以“%E7%BC%96%E7%A0%81”就是在每一个字节前面加上一个“%”获得的,也就是说URL路径使用的是UTF-8编码。