【簡介】
最近我要解析一個數據庫中間件的日志、這個中間件會在日志中記錄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 <module> for line in proxy_backup_log_handler: File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/codecs.py", line 321, in decode (result, consumed) = self._buffer_decode(data, self.errors, final) 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]=i print("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='Ñî°×ÀÍ';
雖然是亂碼,但是絕對不會有異常發生。
---
