【简介】
最近我要解析一个数据库中间件的日志、这个中间件会在日志中记录SQL发往的后台DB ,执行耗时,对应的SQL;中间件直接把SQL写到
了日志中去,并没有对SQL进行适当的编码转换;理想情况下这个也不会有什么问题,不幸的是我就面对着这种情况,client的发给中间件
的SQL有可能是"utf-8",也有可能是"gbk",也有可能是"gb2132";所以使用中间件的日志文件用任何一种编码方式都不成正确的解码它,
幸运的是我要做的工作只要解决出日志中所涉及到的数据库名和表名就行,所以我并不一定要完全解码这个文件。
【复现一下那个中间件写日志的大致逻辑】
以下我会用python代码来描述上面的情况,可以看到对于同一个文件以不同的编码写入了内容
with open('proxy_backup_sql.log','bw') as user_log_hander:user_log_hander.write("192.186.100.10 | 0.012 | select id from tempdb.person where name='张三'; \n".encode('utf8'))user_log_hander.write("192.186.100.10 | 0.012 | select id from tempdb.person where name='杨白劳'; \n".encode('gbk'))
对于上面的情况不管你是用utf-8 还是用gbk打开文件它们会乱码的、
【用什么编码都是不可能正常打开这个文件的】
1、UTF8打开
with open('proxy_backup_sql.log','r',encoding='utf8') as proxy_backup_log_handler:for line in proxy_backup_log_handler:print(line,end='')Traceback (most recent call last):File "main.py", line 22, in
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd1 in position 142: invalid continuation byte
2、用gbk打开
with open('proxy_backup_sql.log','r',encoding='gbk') as proxy_backup_log_handler:for line in proxy_backup_log_handler:print(line,end='')192.186.100.10 | 0.012 | select id from tempdb.person where name='寮犱笁';
192.186.100.10 | 0.012 | select id from tempdb.person where name='杨白劳';
可以看到没有报异常、但是这个只是巧合、gbk刚好能解码utf8编码下的“张三”并把它解码成了“寮犱笁”
【latin-1 有的牛逼之处】
latin-1 这个字符集的牛逼之处、latin-1字符集是在ascii码上的一个扩展,它把ascii码没有用到过的字节码都给编上了对应的字符,所以它能表示
的字符就更多了;针对单个字节来说就没有它不能解码的,这个就是它的牛逼之处所在。也就是说当我们不在乎内容中多字节码的正确怕的情况
下使用latin-1字符集是不会出现解码异常的
以下代码可以说明latin-1可以解码任意的单个字节
#!/usr/bin/env python3
#! -*- coding:utf8 -*-
ba = bytearray(256)
for i in range(256):ba[i]=iprint("number = {0} char = {1}".format(i,ba[i:i+1].decode('latin-1')) )
【在我们不在乎多字节码的情况性的情况下latin-1真的是无敌了】
latin-1可以解码任意文件如果你只是在意单字节码中的内容的话
#!/usr/bin/env python3
#! -*- coding:utf8 -*-if __name__ == "__main__":with open('proxy_backup_sql.log','r',encoding='latin-1') as proxy_backup_log_handler:for line in proxy_backup_log_handler:print(line,end='')
可以看到如下的输出
192.186.100.10 | 0.012 | select id from tempdb.person where name='å¼ ä¸';
192.186.100.10 | 0.012 | select id from tempdb.person where name='Ñî°×ÀÍ';
虽然是乱码,但是绝对不会有异常发生。
---