发布时间:2019-09-27 07:06:38编辑:auto阅读(1635)
【环境】
Windows 10 x64
Python 3.6.3
【关于 gb18030 编码】
GB 18030 wiki:https://zh.wikipedia.org/wiki/GB_18030
单字节,其值从0到0x7F。
双字节,第一个字节的值从0x81到0xFE,第二个字节的值从0x40到0xFE(不包括0x7F)。
四字节,第一个字节的值从0x81到0xFE,第二个字节的值从0x30到0x39,第三个字节从0x81到0xFE,第四个字节从0x30到0x39。
【解码错误的处理方式】
错误:
UnicodeDecodeError: 'gb18030' codec can't decode byte 0xff in position 129535: illegal multibyte sequence
异常对象:UnicodeDecodeError
import codecs # gb18030 乱码 handler def WalkerGB18030ReplaceHandler(exc): print('exc.start: %d' % exc.start) print('exc.end: %d' % exc.end) print('exc.encoding: %s' % exc.encoding) print('exc.reason: %s' % exc.reason) text = '' for ch in exc.object[exc.start:exc.end]: print('ch:') print(ch) text += ('0x%02X' % ch) return (text, exc.end) # 注册自定义handler codecs.register_error("myreplace", WalkerGB18030ReplaceHandler)
* 方案二:自定义编码清洗
# 修理 gb18030文件 # 将乱码转化为十六进制字符串,例如:b'\xff' 转为字符串 0xFF # 将不可打印单字节转为十六进制字符串,例如:b'\xff' 转为字符串 0x7F # srcFile 为原始 gb18030文件 # dstFile 为修理后的 gb18030文件 # explicit 控制是否转换为不可打印字符: explicit 为 False 是不转换(默认),否则转换 def RepairGB18030File(srcFile, dstFile, explicit=False): with open(srcFile, mode='rb') as fin: byteText = fin.read() byteLength = len(byteText) print('byteLength: %d' % byteLength) pos = 0 # 位置 byteList = list() # 末尾添加2对\r\n防止pos溢出 byteText += b'\x0d\x0a\x0d\x0a' while pos < byteLength: byte1 = bytes([byteText[pos]]) byte2 = bytes([byteText[pos+1]]) byte3 = bytes([byteText[pos+2]]) byte4 = bytes([byteText[pos+3]]) # 单字节汉字(正常) if b'\x00' <= byte1 <= b'\x7f': pos += 1 if byte1.decode('gb18030').isprintable(): # 可打印字符 byteList.append(byte1) continue if byte1 in (b'\x0d', b'\x0a'): # 换行符 byteList.append(byte1) continue if explicit: # 要求转换不可打印字符 byteNew = ("0x%02X" % ord(byte1)).encode('gb18030') byteList.append(byteNew) else: # 不要求转换不可打印字符 byteList.append(byte1) # 多字节汉字(双字节或四字节) elif b'\x81' <= byte1 <= b'\xfe': #双字节(正常) if (b'\x40' <= byte2 <= b'\x7e') or (b'\x80' <= byte2 <= b'\xfe'): pos += 2 byteList.extend([byte1, byte2]) continue #四字节 if b'\x30' <= byte2 <= b'\x39': # 四字节(正常) if (b'\x81' <= byte3 <= b'\xfe') or (b'\x30' <= byte4 <= b'\x39'): pos += 4 byteList.extend([byte1, byte2, byte3, byte4]) continue # 四字节乱码 pos += 1 #错误的时候只能移动一个字节 byteNew = ("0x%02X" % ord(byte1)).encode('gb18030') byteList.append(byteNew) continue # 双字节乱码 #0x00-0x2f、0x7f、0xff pos += 1 #错误的时候只能移动一个字节 byteNew = ("0x%02X" % ord(byte1)).encode('gb18030') byteList.append(byteNew) else: # 单字节乱码 #应该只剩 0x80 和 0xff byteNew = ("0x%02X" % ord(byte1)).encode('gb18030') #4个字节 pos += 1 #错误的时候只能移动一个字节 byteList.append(byteNew) repairedText = b''.join(byteList).decode('gb18030') with open(dstFile, mode='w', encoding='gb18030') as fout: fout.write(repairedText)
【相关阅读】
*** walker 的流水账 ***
上一篇: python3发送邮件
下一篇: Python3下map函数的问题
47751
46255
37137
34644
29234
25894
24763
19867
19429
17918
5721°
6325°
5843°
5893°
6994°
5832°
5852°
6366°
6320°
7685°