引用
普通部分
rb主要是為了讀取二進制文件而創(chuàng)立的字段,因為二進制字段中很有可能有1A(\x)這個編碼,但是這個在普通文件中表示的EOF,即文檔結(jié)束符,所以如果使用r讀取二進制文件就會造成將1A當成文件結(jié)束符,導(dǎo)致這個字符后面的部分沒有讀取上,出現(xiàn)文檔讀取不全的現(xiàn)象。
如果我們讀取人工書寫的數(shù)據(jù)那么就使用r,如果我們讀取非人工書寫的數(shù)據(jù)那么我們就是使用rb,圖片就是一種非常典型的非人工書寫數(shù)據(jù)。
with open('photo.jpg', 'rb') as f:
jpgdata = f.read()
高階部分
- 如果使用的mode是
r,那么你就要非常清楚,這個數(shù)據(jù)是用什么編碼來書寫的,讀取的時候也要用對應(yīng)的編碼,否則就有可能由于解碼錯誤,導(dǎo)致亂碼。因為對于計算機來說,只有字符(byte),而沒有(str),而將byte翻譯成str的方式就是依據(jù)encoding的方式而定的,所以我們可以通過設(shè)置encoding字段來指定解碼格式,utf-8是現(xiàn)在的主流編碼方式,如果沒有指定encoding 的方式那么根據(jù)python版本的不同會有不同的解碼方式,Python3中是utf-8,而python2中是ascii。
>>> # Python2
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> # Python3
>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
- open函數(shù)返回的是一個句柄,是將操作系統(tǒng)所持有的句柄交給open函數(shù),當然我們需要對文件操作結(jié)束以后調(diào)用close函數(shù),將關(guān)閉這個句柄,因為每個程序打開文件數(shù)量是有上限的,只有打開之后進行關(guān)閉,才不會觸及這個上限,但是有個問題就是如果在open函數(shù)和close函數(shù)之間程序運行發(fā)生了錯誤,那么就會導(dǎo)致句柄沒有關(guān)閉,這不是我們希望看到了,所以為了保證是否有錯誤發(fā)生都要關(guān)閉句柄,我們可以使用with語句,句柄只有在with語句內(nèi)部是可以使用的,如果在with語句外面(比如出錯時候的traceback)句柄是自動關(guān)閉的,所以就解決了這一個痛點。
小例子
b,u,r
因為在window系統(tǒng)里面 回車是用\r\n表示的,Linux系統(tǒng)離水面回車使用\n表示的,說明mode是rb的時候,寫的時候系統(tǒng)寫進文件的二進制編碼是什么就按什么方式呈現(xiàn)出來,字符串前面是b表示這個是一個byte類型的對象,只不過輸出臺將這個轉(zhuǎn)換成了人能讀懂的形式。
f=open('C:\\Users\\MapReducer\\Desktop\\text.txt','rb')
for line in f:
print(line)
>>
#
b'name: James\r\n'
b'age: 20\r\n'
b'---\r\n'
b'name: Lily\r\n'
b'age: 19'
因為文件中每一行的末尾有一個回車,print函數(shù)也會自己在輸出一個回車,所以輸出兩個空格,說明了如果mode是r的話,人寫進去的是什么形式的讀出來就是什么形式的,不管在什么系統(tǒng)下回車的編碼方式是什么。
f=open('C:\\Users\\MapReducer\\Desktop\\text.txt','r')
for line in f:
print(line)
>>
name: James
age: 20
---
name: Lily
age: 19