Python基础知识之文件的读取操作
讀取文件的操作步驟
有一道腦筋急轉(zhuǎn)彎,問把大象裝進冰箱的步驟,答案很簡單,打開冰箱、把大象推進去、關(guān)閉冰箱。這就是一個處理問題的思路,我們對文件的操作和這個一樣,第一步:打開文件;第二部:處理文件(讀取或者寫入);第三部關(guān)閉文件,怎么樣?其實很簡單吧,下面我們就來詳細(xì)說說文件的操作。
打開文件
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)打開文件要使用open()函數(shù),()內(nèi)涉及的參數(shù)在初期階段我們只需要知道三個參數(shù)即可,那就是file、mode、和encoding
file
首先是文件名,類型是字符串,要包含路徑,如果要打開的文件和當(dāng)前文件在同一個目錄下則可以省略路徑(相對路徑).
mode
然后是打開文件的模式,格式是:mode='模式', 這里的"mode="可以省略,直接寫模式即可,如果不指定模式則默認(rèn)為r,具體的模式如下:
這里引入一個偽名詞——指針,想象一下當(dāng)你在word中編輯文本時有個光標(biāo)吧?你可以把指針想象成那個光標(biāo),光標(biāo)在哪里你對文件的所有操作就從哪里開始。
encoding
第三個參數(shù)是文件的編碼(非二進制格式時使用),編碼的設(shè)置必須與要打開的文件的編碼一致,否則會報錯,也就是說源文件是用什么編碼寫入的,你打開時就得用什么編碼打開。
處理文件
我們來舉一個出錯的例子,要實現(xiàn)的操作是打開文件名為“test”的文件,原文件編碼為utf-8,而我們打開時使用了gbk編碼。
文件中只有一句話:十步殺一人,千里不留行。
代碼如下:
這里說明以下,open函數(shù)返回的結(jié)果是一個文件對象,所以要用一個變量接收一下(file),
這樣我們就可以方便地使用這個對象的方法了,比如file.read(),file.write,file.flush()等等
read()是文件對象的一個方法,作用是讀取指定的字符數(shù),如果未指定則默認(rèn)讀取所有內(nèi)容
但是上面的代碼執(zhí)行后會報錯,下面是報錯信息,大意是gbk編碼無法解碼(文件打開的過程實際就是解碼的過程)
解決的辦法很簡單,把編碼方式改為utf-8即可,因為linux系統(tǒng)默認(rèn)是utf-8編碼,所以編碼也可以省略不寫,又因為我們只是要讀取下文件,所以模式為r,而默認(rèn)模式為r,也可以省略不寫。
所以代碼就變成了下面的樣子:
方法read()中也可以添加數(shù)字參數(shù),作用是指定讀取的字符數(shù),不管是漢字還是字母一個字符對應(yīng)一個字母或者漢字,這里一定要和字節(jié)區(qū)分開,例子如下:
file = open('test') content = file.read(3) print(content) file.close() 輸出為: 十步殺我們之前使用的打開文件的方式比較麻煩,因為必須要在結(jié)束時寫關(guān)閉文件的語句,這里介紹一種簡便的方法,格式是:
with open() as file_name:操作代碼......使用這種方法的好處是不用寫關(guān)閉文件的語句,with 和as是關(guān)鍵字,記住格式即可.
接下來我們創(chuàng)建一個二進制格式的文件
因為我們打開文件的方式是以二進制格式打開的,那么在寫入文件時就要寫入二進制格式的字符串,但是對于”十步殺一人,千里不留行“這個字符串的二進制格式是什么呢?我們并不知道,所以我們使用.encode(utf8)來把這個字符串轉(zhuǎn)換成二進制格式。實際上我們通過另外一段代碼是可以知道這個字符串對應(yīng)的二進制格式的,代碼如下:
print('十步殺一人,千里不留行'.encode('utf8')) 輸出的二進制格式(表現(xiàn)形式為16進制,為什么?因為二進制太長了啊!!!)為: b'\xe5\x8d\x81\xe6\xad\xa5\xe6\x9d\x80\xe4\xb8\x80\xe4\xba\xba\xef\xbc\x8c\xe5\x8d\x83\xe9\x87\x8c\xe4\xb8\x8d\xe7\x95\x99\xe8\xa1\x8c'在實際中我們當(dāng)然不可能寫這么長的東西,所以我們使用.encode('utf8')來轉(zhuǎn)化。轉(zhuǎn)化時我們使用了utf-8的編碼方式。
在這里說明一下為什么要編碼,想弄清楚這件事就要明白計算機的存儲原理。
簡單地講,文件在計算機中都是以二進制格式存儲的,對于計算機來講只有兩個數(shù)字有意義,那就是0和1,也就是二進制,而不同的0和1的組合代表不同的含義(編碼不同),比如在gbk編碼下一個漢字由兩個字節(jié)表示,也就是16位二進制數(shù)(16個0和1的組合),而在utf-8編碼下一個漢字由3個字節(jié)表示,也就是24位二進制數(shù)(24個0和1的組合),而我們現(xiàn)在要給計算機存儲的就是0和1的組合,那么在讀取文件或者轉(zhuǎn)化字符串時,如果你不告訴計算機你使用的是哪種編碼的話,計算機怎么可能知道這些0和1的組合代表什么含義呢?所以從計算機取出數(shù)據(jù)或者把普通字符串轉(zhuǎn)化成二進制格式時你必須告訴計算機你使用的是什么編碼方式。
在本例中使用utf-8編碼,所以在字符串后面加上.encode(utf8)
那么為什么平時可以直接寫入普通字符串呢?那是因為在用open()函數(shù)打開文件的時候就已經(jīng)指定了編碼方式。
形象地解釋:open函數(shù)相當(dāng)于打開了一種通道,平時打開時都是用某種編碼的方式打開的,所以我們在寫入內(nèi)容時不必管它以什么編碼進入通道的(因為在open函數(shù)里面就已經(jīng)指定了編碼方式)
而當(dāng)open函數(shù)使用二進制格式打開時(就是帶b的模式),這個通道就沒有指定編碼方式,通道里面只有二進制,所以此時往通道里面放入非二進制格式內(nèi)容的話就需要指定一種編碼方式。除非你直接在file.write()函數(shù)中直接寫二進制,但是人類是不可能記住那么多二進制組合所代表的含義的。
然后我們來讀取一下上面創(chuàng)建的名字為“二進制”的這個文件
with open('二進制','rb') as file:print('不指定解碼方式時的結(jié)果:',file.read())如果我們在讀取時不指定解碼方式,那么輸出的結(jié)果就是下面這種人類無法理解的奇怪的東西(實際上它是用16進制表示的二進制)
不指定解碼方式時的結(jié)果: b'\xe5\x8d\x81\xe6\xad\xa5\xe6\x9d\x80\xe4\xb8\x80\xe4\xba\xba\xef\xbc\x8c\xe5\x8d\x83\xe9\x87\x8c\xe4\xb8\x8d\xe7\x95\x99\xe8\xa1\x8c'所以我們在讀取時也要指定編碼:
with open('二進制','rb') as file:content = file.read()print('指定解碼方式后的結(jié)果:',content.decode('utf-8'))指定解碼方式后的結(jié)果: 十步殺一人,千里不留行其他的在讀取時可能用到的方法:
readline()讀取一行,如果里面添加了參數(shù)n,則會讀取n個字符(我覺得這是個bug,貌似沒什么卵用) readlines()讀取所有內(nèi)容,結(jié)果返回一個列表,元素由每一行組成。 tell()會輸出當(dāng)前指針的位置,注意,該位置是以字節(jié)來計算的,不是字符 seek()重新指定指針位置。使用readlines()并不是一個好方法,因為是一次性將文件都讀取到內(nèi)存中,如果文件較大時則造成內(nèi)存溢出,實際中使用下面的方法,系統(tǒng)會自動生成一個迭代器,用迭代的方法把需要的數(shù)據(jù)取出來。
with open('libai') as f:for i in f: #這里的i實際就是迭代后的每一行,用for循環(huán)的方式從文件對象中取出來,取一行讀一行,節(jié)省內(nèi)存print(i) 趙客縵胡纓,吳鉤霜雪明。銀鞍照白馬,颯沓如流星。十步殺一人,千里不留行。事了拂衣去,深藏身與名。閑過信陵飲,脫劍膝前橫。將炙啖朱亥,持觴勸侯嬴。三杯吐然諾,五岳倒為輕。眼花耳熱后,意氣素霓生。救趙揮金錘,邯鄲先震驚。千秋二壯士,烜赫大梁城。 縱死俠骨香,不慚世上英。誰能書閣下,白首太玄經(jīng)。關(guān)閉文件
如果用with open() 來打開文件的話就不用管關(guān)閉文件的操作了,因為Python已經(jīng)幫你完成了這一步,否則必須在處理文件之后加上關(guān)閉文件的操作:file_name.close()
總結(jié)
以上是生活随笔為你收集整理的Python基础知识之文件的读取操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: The road to learning
- 下一篇: hadoop目录命令