Part A.编码问题
表格挺清晰的,不过奇怪赞同人少、ASCII码-2/10/16进制对照表
这四个我没细看:比较长篇的参考1、比较长篇的参考2、参考3-廖雪峰py3、参考4-廖雪峰py2
一、内容比较复杂,我直接说我常用的
(1)unicode 是最底层的通用编码。
(2)流行的是 utf-8 编码,这是因为utf-8是不定长的。对英文、中文等都友好点。
(3)ASCII 码,长度小范围小,不支持中文。
(4)对于英语字母,UTF-8 编码和 ASCII 码是相同的。
(5)python字符串的类型只有两种 str,bytes 。
(6)python3里面 str 是 unicode 编码。
>>> "我们" == u"我们"
True
(7)python3里面 bytes 类型字符串是根据指定编码 encode生成的,它不是二进制字符串,而是比特流的意思!!bytes 字符串的组成形式,必须是十六进制数,或者ASCII字符。 参考博客
>>> "我们".encode("gbk")
b'\xce\xd2\xc3\xc7'
>>> "我们".encode("utf8") # 可见gbk、utf-8的编码得到的 bytes 字符串是不同的。
b'\xe6\x88\x91\xe4\xbb\xac'
>>> "我们".encode() # py3默认编码是utf-8
b'\xe6\x88\x91\xe4\xbb\xac'
>>> "我们".decode("utf8") # 原本的是 unicode 码,已经是最底层编码了,所以decode会报错。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'decode'
二、python打印的print
未必是目标编码字符串(二进制),通常是转换过了的。就比如'\x4E'
实际打印的是ascii编码或说utf8编码的N
。
>>> my_data = '\x4E' # ascii码对应标:十六进制对应的图形是"N"
>>> my_data
'N'
>>> my_data = b'\x4E'
>>> my_data
b'N'
>>> my_data = 0x4E # ascii码对应标:十六进制对应的十进制是78
>>> my_data
78
>>> chr(78) # 把一个十进制转换成ASCII码表中对应的单个字符
'N'
>>> ord('N') # 把ASCII码表中的字符转换成对应的十进制
78
三、十进制与ascii的转换
1、chr():把一个十进制转换成ASCII码表中对应的单个字符
>>> chr(98)
'b'
>>> chr(97)
'a'
2、ord():和chr相反,把ASCII码表中的字符转换成对应的十进制
>>> ord('b')
98
>>> ord('c')
99
Part B.进制转换
一、不同进制之间的转换
1、二进制与十六进制之间的转换:用binascii库
二进制转为十六进制的函数:binascii.b2a_hex()、binascii.hexlify()
十六进制转为二进制的函数:binascii.a2b_hex()、binascii.unhexlify()
#coding:utf-8
import binascii
a = 'worker'
b = binascii.b2a_hex(a) # 二进制转为十六进制
print(b) # 输出:776f726b6572
t = binascii.a2b_hex(b) # 十六进制转为二进制。与b2a_hex相反。
print(t) # 输出 worker
c = binascii.hexlify(a) # 二进制转为十六进制。和b2a_hex()一样
print(c) # 输出:776f726b6572
d = binascii.unhexlify(c) # 十六进制转为二进制。和a2b_hex()一样。
print(d) # 输出:worker
2、十进制与其它进制的转换:python内置函数
(1)hex() 把10进制转换成16进制
>>> hex(88)
'0x58'
#把浮点型转换成16进制
>>> 1.23.hex()
'0x1.3ae147ae147aep+0'
(2)bin():把十进制整型转换成二进制字符
>>> bin(88)
'0b1011000'
>>> bin(33)
'0b100001'
(3)oct():把十进制转换成八进制字符
>>> oct(500)
'0764'
>>> oct(488)
'0750'
3、读取任意进制字符串:np.fromstring()
参考官方、参考博客
numpy.fromstring(string, dtype=float, count=-1, sep=’’)
参数说明:
string : str 输入字符串
dtype : data-type, optional 控制生成的array的dtype。如果是二进制输入,就一定要输入输出相匹配,此时通常是np.uint8。
count : int, optional 读取多少个数据。可以不用管。
sep : str, optional 分割符
例子:
>>> np.fromstring('1 2', dtype=int, sep=' ')
array([1, 2])
>>> np.fromstring('1, 2', dtype=int, sep=',')
array([1, 2])
>>> np.fromstring('\x60', dtype=np.uint8)
array([96], dtype=int8)
二、概念
1、普通文本文件与二进制文件的差别
读取时的区别:二进制可以每个字符为一位,不会出现中文字符需要占据多位问题,但是需要进行encode才能知道具体的字符串。
在python的load_word2vec_format函数里面有具体区别的代码:
gensim.models.KeyedVectors.load_word2vec_format(‘vectors.bin’, binary=True)
注:c语言的fgetc函数,暂时我觉得它不能够直接读取中文字符,不过可以读取中文字符的二进制格式。具体的我要实践后再确定。
三、python3 遇到的问题及解法
1、解码时报错
(1)原因:某些文件,按照字节大小直接截断,导致编码有问题。
(2)报错例子:
'utf-8' codec can't decode byte 0xe6 in position 0: unexpected end of data
(3)解决方案1:参考
二进制读取文件,读取一行后,就行解码。解码不成功就 ignore,全称 ignore 模式。或者open 函数里面参数设置为 ignore 也行。
with open(in_path, "rb") as f_in:
for line inf_in:
try:
line = line.decode("utf8").strip()
except Exception:
print("error sentance_cnt", sentance_cnt)
print(line)
line = line.decode("utf8", errors='ignore').strip() # 无视解码有问题的模式。默认是strict模式。还有一种是 replace 模式,但不推荐用,它会用一些很奇怪的字符代替无法解码的字符。
print(line)
解决方案2——弃用:参考
之前py2.7还流行时使用的,之前我用过可以。现在可能没什么用了。只当记录一下吧。
import sys
reload(sys)
sys.setdefaultencoding('utf-8')