在學python的open函數時,我發現在pycharm里新建一個file_name.txt文本文件,輸入中文保存,再用open(file_name,'r+')打開,再去讀寫時出現了一些小問題。利用Notepad和EditPlus進行多輪控制變量測試后,總結如下:
1、當原文件為utf8編碼格式,且不包含中文,則對其進行讀操作,正常;對其進行寫操作(非中文),正常,文件編碼格式不變;
當寫入中文字符時,文件編碼格式變為gbk,此時pycharm中的文件會將你輸入的中文顯示為16進制數,並會提示你用gbk編碼reload文件。
2、當原文件為utf8編碼格式,若包含中文,此時對其進行讀操作,則可能報錯UnicodeDecodeError,也可能不報錯。是否報錯跟中文內容有關。
寫入中文情況與1相同。
如,新建一個文件file4.txt,里面寫入"你好"兩個漢字,然后去讀它:
結果為:

為什么是 " 浣 犲 ソ " 這三個陌生的玩意呢?查看“你好”的utf8編碼16進制表示:
再查看這三個字符的GBK編碼16進制表示:
瞬間明白了:open函數用GBK解碼了被UTF-8編碼的file4文件。前者用兩個字節表示一個漢字而后者用三個。
把“你好”換成“中國”再試一次:報錯了!
因為“中國”的編碼前兩個字節E4B8根本就沒有對應的GBK編碼字符。
open的encoding默認為'gbk',可將其改為'utf-8'.
改后也可能會出錯!
如:file4輸入中英混合的,hello中國
再對其進行覆蓋寫:
其utf8 16進制表示為:
68 65 6C 6C 6F E4 B8 AD E5 9B BD
覆蓋寫入"天青色"后:
E5 A4 A9 E9 9D 92 E8 89 B2 9B BD
還剩個9BBD找不到對應的字符,自然就報錯了:
----------------------------------------------------------------------華麗的分割線-----------------------------------------------------------------------------
補充點編碼知識:
Unicode編碼其實只是個字符集,把全球的字符用唯一的16進制編號表示出來,這個編號就叫“碼位”。最多可表示1114111個,即10FFFF。他沒有規定具體怎么存儲到計算機硬盤中。而UTF-8就是具體編碼的體現,是將碼位轉化為字節序列的一套編碼規則。
如:“漢”字的Unicode編碼是0x6C49。0x6C49在0x0800-0xFFFF之間, 使用3字節模板: 1110xxxx 10xxxxxx 10xxxxxx。將0x6C49寫成二進制是: 0110 1100 0100 1001,用這個二進制數依次代替模板中的x,得到:
11100110 10110001 10001001, 即E6 B1 89。這個就是被存到計算機中的比特流。
utf-8的規則:
1. 單字節的字符,字節的第一位設為0,如英文字母,UTF-8碼只占用一個字節,和ASCII碼完全相同;
2. n個字節的字符(n>1),如中文漢字,第一個字節的前n位設為1,第n+1位設為0,后面字節的前兩位都設為10,這n個字節的其余空位填充該字符unicode碼,高位用0補足。
U+ 0000 ~ U+ 007F: 0XXXXXXX
U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX
U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX
U+10000 ~ U+10FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX