[Python3] 關於Bytes與String 寫檔案遇到的編碼問題

tiny丶發表於2019-01-21

寫前面的話

最近在搞一個python3的專案,其中有個功能需要寫檔案,但是介面傳給我的資料是str型別的。我用str寫檔案的話,由於對於str原始的編碼不能確定,所以檔案就會出現亂碼,大致描述如下:

UnicodeEncodeError: ‘gbk’ codec can’t encode character u’\u200e’ in position 43: illegal multibyte sequence

Bytes與String

python3最重要的新特性大概要算對文字和二進位制資料做了更為清晰的區分,文字總是unicode字符集,有str型別表示,二進位制資料則有bytes型別表示。python3不會以任何隱式的方式混用str和bytes,正是這是的這兩者的區別特別明顯,你不能拼接字串和位元組包,也無法在位元組包裡搜尋字串(反之亦然),也不能將字串傳入引數為位元組包的函式(反之亦然);
在這裡插入圖片描述
程式碼展示:

buf = "我愛祖國"
print (type(buf), buf)
buf2 = buf.encode(encoding='utf-8')
print (type(buf2), buf2)

<class 'str'> 我愛祖國
<class 'bytes'> b'\xe6\x88\x91\xe7\x88\xb1\xe7\xa5\x96\xe5\x9b\xbd'

decode函式與encode函式使用

1. decode()函式

描述:以 encoding 指定的編碼格式解碼Bytes型別資料,解碼後的資料型別為:<class ‘str’>

2. encode()函式

描述:以 encoding 指定的編碼格式對string型別資料轉碼,編碼後的資料型別為:<class ‘bytes’>

  • encoding ——要使用的編碼,如:utf-8,gb2312,cp936,gbk等。

  • errors ——設定不同解碼錯誤的處理方案。預設為 ‘strict’,意為編碼錯誤引起一個 UnicodeDecodeError。 其它可能得值有 ‘ignore’, 'replace’以及通過 codecs.register_error() 註冊的1其它值。

程式示例:

s = "我愛祖國"
str1 = s.encode(encoding="utf-8",errors="strict")
str2 = s.encode("gb2312") #編碼錯誤的處理方案預設為"strict"
str3 = s.encode("gbk")
print (type(str1), type(str2), type(str3))

print(str1.decode(encoding="utf-8",errors="strict"))#用utf-8的解碼格式,解碼str1.
print(str1.decode(encoding="gbk",errors="ignore"))  ##如果以gbk的解碼格式對str1進行解碼得,將無法還原原來的字串內容
print(str1.decode(encoding="gbk",errors="strict"))
print(str1.decode(encoding="gbk",errors="replace"))
print(str2.decode("gb2312"))
print(str3.decode("gbk"))

結果展示:

<class 'bytes'> <class 'bytes'> <class 'bytes'>
我愛祖國
鎴戠埍紲栧浗
鎴戠埍紲栧浗
鎴戠埍紲栧浗
我愛祖國
我愛祖國

檔案操作問題

除了在資料的處理上有二進位制bytes和字串string區分,其實寫檔案的時候也有區分。同樣寫檔案的時候也有編碼的區分,尤其當輸入文字型別為string型別的時候。

import requests
s = requests.get('http://www.12306.cn/mormhweb')
with  open('12306.html','w', encoding='utf-8') as fd:
    fd.write(s.content.decode('UTF-8',errors='replace'))

我們看到 encoding=‘utf-8’ 說明寫入檔案的編碼方式為utf-8,與文字解碼出來的格式是一樣的。如果我們把 encoding='gbk’那麼可想而知,得出的結果就不一定對了。

filerad = open(‘C:/Users/Administrator/Desktop/randomnum.txt’,‘wb’) # 以二進位制方式進行寫入

以下為open模式:

  • r 開啟只讀檔案,該檔案必須存在。
  • r+ 開啟可讀寫的檔案,該檔案必須存在。
  • w 開啟只寫檔案,若檔案存在則檔案長度清為0,即該檔案內容會消失。若檔案不存在則建立該檔案。
  • w+ 開啟可讀寫檔案,若檔案存在則檔案長度清為零,即該檔案內容會消失。若檔案不存在則建立該檔案。
  • a 以附加的方式開啟只寫檔案。若檔案不存在,則會建立該檔案,如果檔案存在,寫入的資料會被加到檔案尾,即檔案原先的內容會被保留。
  • a+ 以附加方式開啟可讀寫的檔案。若檔案不存在,則會建立該檔案,如果檔案存在,寫入的資料會被加到檔案尾後,即檔案原先的內容會被保留。

上述的形態字串都可以再加一個b字元,如rb、w+b或ab+等組合,加入b 字元用來告訴函式庫開啟的檔案為二進位制檔案,而非純文字檔案。不過在POSIX系統,包含Linux都會忽略該字元。

結論

說了這麼多,其實py3的 關於bytes與str的區分已經給了我們答案了!come on!
很多時候,如果不知道解決方法,是否可以回過頭再梳理一下基礎知識呢!!

備註:
在python3呼叫 vs dll時候,傳參為bytes 格式!!!!否則傳參就會錯誤!

相關文章