Python檔案讀取操作的詳細介紹

不言
發布: 2018-10-09 16:29:30
轉載
2713 人瀏覽過

這篇文章帶給大家的內容是關於Python檔案讀取操作的詳細介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

讀取文件的操作步驟

有一道腦筋急轉彎,問把大象裝進冰箱的步驟,答案很簡單,打開冰箱、把大象推進去、關閉冰箱。這就是一個處理問題的思路,我們對文件的操作和這個一樣,第一步:開啟文件;第二部:處理文件(讀取或寫入);第三部關閉文件,怎麼樣?其實很簡單吧,下面我們就來詳細說說文件的操作。

開啟檔案

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
登入後複製

開啟檔案要使用open()函數,()內涉及的參數在初期階段我們只需要知道三個參數即可,那就是file、mode、和encoding

file

首先是檔案名,類型是字串,要包含路徑,如果要開啟的檔案和目前檔案在同一個目錄下則可以省略路徑(相對路徑).

mode

#然後是開啟檔案的模式,格式是:mode='模式', 這裡的" mode="可以省略,直接寫模式即可,如果不指定模式則預設為r,具體的模式如下:
這裡引入一個偽名詞——指針,想像一下當你在word中編輯文本時有個遊標吧?你可以把指針想像成那個遊標,遊標在哪裡你對文件的所有操作就從哪裡開始。

r 
只读。文件的初始指针在文件的开头。这是默认模式。
rb
只读的二进制格式。文件的初始指针在文件的开头。
r+
读写。文件的初始指针在文件的开头。
rb+
读写的二进制格式。文件的初始指针在文件的开头。
w
只写。如果该文件已存在则打开文件,清空文件内容。如果该文件不存在,则创建新文件。
wb
只写的二进制格式。如果该文件已存在则打开文件,清空文件内容。如果该文件不存在,创建新文件。
w+
写读。如果该文件已存在则打开文件,清空文件内容。如果该文件不存在,创建新文件。
wb+
写读的二进制格式。如果该文件已存在则打开文件,清空文件内容。如果该文件不存在,创建新文件。
a
追加写。如果该文件存在,文件的初始指针在文件的结尾。新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab
追加写的二进制格式。如果该文件存在,文件的初始指针在文件的结尾。新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+
追加写读。如果该文件已存在,文件的初始指针在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+
追加写读的二进制格式。如果该文件已存在,文件的初始指针在文件的结尾。如果该文件不存在,创建新文件用于读写。
登入後複製

encoding

第三個參數是檔案的編碼(非二進位格式時使用),編碼的設定必須與要開啟的檔案的編碼一致,否則會報錯,也就是說原始檔案是用什麼編碼寫入的,你打開時就得用什麼編碼打開。

處理文件

我們來舉一個出錯的例子,要實現的操作是打開文件名為「test」的文件,原始文件編碼為utf-8 ,而我們打開時使用了gbk編碼。
文件中只有一句話:十步殺一人,千里不留行。
程式碼如下:

file = open('test','r',encoding='gbk')
content = file.read()
print(content)
file.close()
登入後複製

這裡說明以下,open函數傳回的結果是一個文件對象,所以要用一個變數接收一下(file),
這樣我們就可以方便地使用這個對象的方法了,例如file.read(),file.write,file.flush()等等
read()是檔案物件的一個方法,作用是讀取指定的字元數,如果未指定則預設讀取所有內容
但是上面的程式碼執行後會報錯,下面是報錯訊息,大意是gbk編碼無法解碼(檔案開啟的過程實際上就是解碼的過程)

    ---------------------------------------------------------------------------

    UnicodeDecodeError                        Traceback (most recent call last)

    <ipython-input-78-bb879f008680> in <module>()
          4 #这里说明以下,open函数返回的结果是一个文件对象,所以要用一个变量接收一下(file),这样我们就可以方便地使用这个
          5 #对象的方法了,比如file.read(),file.write,file.flush()等等
    ----> 6 content = file.read()#read()是文件对象的一个方法,作用是读取指定的字符数,如果未指定则默认读取所有内容
          7 print(content)
          8 file.close()

    UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 4: illegal multibyte sequence
登入後複製

解決的辦法很簡單,把編碼方式改為utf-8即可,因為linux系統預設是utf-8編碼,所以編碼也可以省略不寫,又因為我們只是要讀取下文件,所以模式為r,而預設模式為r,也可以省略不寫。
所以程式碼就變成了下面的樣子:

file = open('test')
content = file.read()
print(content)
file.close()
输出为:
十步杀一人,千里不留行
登入後複製

方法read()中也可以加入數字參數,作用是指定讀取的字元數,不管是漢字還是字母一個字元對應一個字母或漢字,這裡一定要和字節區分開,例子如下:

file = open('test')
content = file.read(3)
print(content)
file.close()
输出为:
十步杀
登入後複製

我們之前使用的打開文件的方式比較麻煩,因為必須要在結束時寫關閉文件的語句,這裡介紹一種簡便的方法,格式是:

with open() as file_name:
    操作代码......
登入後複製

使用這種方法的好處是不用寫關閉檔案的語句,with 和as是關鍵字,記住格式即可.
接下來我們建立一個二進位格式的檔案

with open('二进制','wb') as file: 
    file.write('十步杀一人,千里不留行'.encode('utf8'))
登入後複製

因為我們開啟檔案的方式是以二進位格式開啟的,那麼在寫入檔案時就要寫入二進位格式的字串,但是對於」十步殺一人,千里不留行「這個字串的二進位格式是什麼呢?我們並不知道,所以我們使用.encode(utf8)來把這個字串轉換成二進位格式。實際上我們透過另外一段程式碼是可以知道這個字串對應的二進位格式的,程式碼如下:

print('十步杀一人,千里不留行'.encode('utf8'))
输出的二进制格式(表现形式为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'
登入後複製

在实际中我们当然不可能写这么长的东西,所以我们使用.encode('utf8')来转化。转化时我们使用了utf-8的编码方式。
在这里说明一下为什么要编码,想弄清楚这件事就要明白计算机的存储原理。
简单地讲,文件在计算机中都是以二进制格式存储的,对于计算机来讲只有两个数字有意义,那就是0和1,也就是二进制,而不同的0和1的组合代表不同的含义(编码不同),比如在gbk编码下一个汉字由两个字节表示,也就是16位二进制数(16个0和1的组合),而在utf-8编码下一个汉字由3个字节表示,也就是24位二进制数(24个0和1的组合),而我们现在要给计算机存储的就是0和1的组合,那么在读取文件或者转化字符串时,如果你不告诉计算机你使用的是哪种编码的话,计算机怎么可能知道这些0和1的组合代表什么含义呢?所以从计算机取出数据或者把普通字符串转化成二进制格式时你必须告诉计算机你使用的是什么编码方式。
在本例中使用utf-8编码,所以在字符串后面加上.encode(utf8)

那么为什么平时可以直接写入普通字符串呢?那是因为在用open()函数打开文件的时候就已经指定了编码方式。
形象地解释:open函数相当于打开了一种通道,平时打开时都是用某种编码的方式打开的,所以我们在写入内容时不必管它以什么编码进入通道的(因为在open函数里面就已经指定了编码方式)
而当open函数使用二进制格式打开时(就是带b的模式),这个通道就没有指定编码方式,通道里面只有二进制,所以此时往通道里面放入非二进制格式内容的话就需要指定一种编码方式。除非你直接在file.write()函数中直接写二进制,但是人类是不可能记住那么多二进制组合所代表的含义的。

然后我们来读取一下上面创建的名字为“二进制”的这个文件

with open('二进制','rb') as file:
    print('不指定解码方式时的结果:',file.read())
登入後複製

如果我们在读取时不指定解码方式,那么输出的结果就是下面这种人类无法理解的奇怪的东西(实际上它是用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'
登入後複製

所以我们在读取时也要指定编码:

with open('二进制','rb') as file:
    content = file.read()
    print('指定解码方式后的结果:',content.decode('utf-8'))

指定解码方式后的结果: 十步杀一人,千里不留行
登入後複製

其他的在读取时可能用到的方法:

readline()读取一行,如果里面添加了参数n,则会读取n个字符(我觉得这是个bug,貌似没什么卵用)
readlines()读取所有内容,结果返回一个列表,元素由每一行组成。
tell()会输出当前指针的位置,注意,该位置是以字节来计算的,不是字符
seek()重新指定指针位置。
登入後複製

使用readlines()并不是一个好方法,因为是一次性将文件都读取到内存中,如果文件较大时则造成内存溢出,实际中使用下面的方法,系统会自动生成一个迭代器,用迭代的方法把需要的数据取出来。

with open('libai') as f:
    for i in f: #这里的i实际就是迭代后的每一行,用for循环的方式从文件对象中取出来,取一行读一行,节省内存
        print(i)
登入後複製
赵客缦胡缨,吴钩霜雪明。银鞍照白马,飒沓如流星。

十步杀一人,千里不留行。事了拂衣去,深藏身与名。

闲过信陵饮,脱剑膝前横。将炙啖朱亥,持觞劝侯嬴。

三杯吐然诺,五岳倒为轻。眼花耳热后,意气素霓生。

救赵挥金锤,邯郸先震惊。千秋二壮士,烜赫大梁城。  

纵死侠骨香,不惭世上英。谁能书阁下,白首太玄经。
登入後複製

关闭文件

如果用with open() 来打开文件的话就不用管关闭文件的操作了,因为Python已经帮你完成了这一步,否则必须在处理文件之后加上关闭文件的操作:file_name.close()


以上是Python檔案讀取操作的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!