python I/O+編碼 小例
阿新 • • 發佈:2018-12-22
python3使用Unicode編碼
str = ord('中') #ord獲取字元整數表示 這個整數表示也就是Unicode編碼去對映的 也就是'中'字在記憶體中真正表示的值 print(str) #在記憶體中以Unicode表示,一個字元對應若干個位元組。如果要在網路上傳輸,或者儲存到磁碟上,就需要把str變為以位元組為單位的bytes str = '中文'.encode('utf-8') #把Unicode字串編碼成utf-8的bytes print(str) #decode把utf-8編碼的bytes解碼成Unicode字串 str = b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8') #'中文'的utf-8編碼的bytes print(str)
output:
20013
b'\xe4\xb8\xad\xe6\x96\x87'
中文
配合編碼進行I/0:
with open('msg.txt', 'wb') as file: s = '中文'.encode('UTF-8') file.write(s) #二進位制開啟檔案 必須寫入bytes 位元組陣列型別,並且不能指定encoding with open('msg.txt', 'w', encoding='UTF-8') as file: s = '中文' #字元形式開啟檔案 寫入的就直接是str型別 按照給定的encoding去寫 file.write(s)
可以看到,如果以二進位制形式開啟檔案,那麼就需要用到上面所說的encode和decode。
這個擴充套件到讀檔案,還有網路流讀寫都是一樣的。理解了最簡單的例子,才能往復雜的去寫,不然越寫越糊塗。
再來看個例子,在記憶體中讀寫,原理是一模一樣的,不過資料交換從記憶體和硬碟變成了記憶體和記憶體:
from io import StringIO with StringIO() as s: s.write('hello') s.write(' ') s.write('world!') #seek已經定位到11 讀寫都會改變seek 就像檔案裡的遊標一樣 print(s.getvalue()) with StringIO('''你好 世界!''') as s: #如果想重新讀上面寫好的StringIO 那麼用seek(0)重新定位即可 ls = s.readlines() for l in ls: print(l,end='') Output: hello world! 你好 世界!
一樣的字元流,為什麼這裡字元流不需要指定編碼?其實之前我有篇部落格你真的明白Java和Python3使用Unicode編碼的含義嗎?已經詳細解釋過了,這個是因為python在記憶體中就是使用的Unicode編碼,我們沒法去改變,而檔案是儲存在硬碟上的,可以有多種編碼方式,所以當指定字元流寫入的時候,可以新增encoding欄位來指定檔案的編碼方式。
當然,如果你執意如此,你可以把字串decode,然後再轉回字串,就像下面這樣,不過,何必呢?
from io import StringIO
with StringIO() as s:
a = str('中國'.encode('UTF-8'))
s.write(a)
print(s.getvalue())
Output:
b'\xe4\xb8\xad\xe5\x9b\xbd'
其實當你要這樣用的時候,需要選擇位元組流BytesIO
from io import BytesIO
with BytesIO() as b:
b.write('中國'.encode('UTF-8'))
print(b.getvalue())
with BytesIO(b'\xe4\xb8\x87\xe5\xb2\x81') as b:
ls = b.readlines()
for l in ls:
print(l.decode(), end='')
Output:
b'\xe4\xb8\xad\xe5\x9b\xbd'
萬歲
可以看到,當改變通訊介質之後,python提供的介面是通用的,唯一不同的就是介質變了。