#20 Python檔案
前言
前面幾節枯燥的模組終於結束了,想要完全掌握前幾節的模組需要不斷的練習才行,畢竟眼過千遍不如手過一遍嘛。在一些專案需求裡,要對檔案進行IO操作,畢竟重要資料不可能列印到螢幕上而不去儲存,Python對的檔案IO操作並不是很複雜,相信你很快就能掌握它!
檔案IO操作
對於一個檔案的操作,無非不過建立、刪除、讀、寫,建立和刪除在OS模組裡面已經說過,那隻剩下讀和寫了,也就是IO(Input,Output)操作了。
接下來,將以徐志摩的《再別康橋》為例子,深入解讀Python中檔案IO操作
輕輕的我走了, 正如我輕輕的來; 我輕輕的招手, 作別西天的雲彩。 ---- 那河畔的金柳, 是夕陽中的新娘; 波光裡的豔影, 在我的心頭盪漾。 ---- 軟泥上的青荇, 油油的在水底招搖; 在康河的柔波里, 我甘心做一條水草! ---- 那榆蔭下的一潭, 不是清泉,是天上虹; 揉碎在浮藻間, 沉澱著彩虹似的夢。 ---- 尋夢?撐一支長篙, 向青草更青處漫溯⑷; 滿載一船星輝, 在星輝斑斕裡放歌。 ---- 但我不能放歌, 悄悄是別離的笙簫; 夏蟲也為我沉默, 沉默是今晚的康橋! ---- 悄悄的我走了, 正如我悄悄的來; 我揮一揮衣袖, 不帶走一片雲彩。
1. 開啟檔案
Python獲得檔案控制代碼的方式與c及其類似,使用內建函式open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) 「file表示檔名、mode表示開啟方式(預設為讀)、buffering表示寄存區緩衝大小(負值為系統預設,0為沒有寄存區快取,1為檔案會寄存行,大於1的整數為寄存區快取大小)、encoding表示檔案編碼、newline表示換行符(預設為\n)」
f = open('再別康橋.txt')# 以預設讀的方式開啟再別康橋,注意:檔案路徑(此時程式和再別康橋在同一路徑) f = open('xxx.txt', 'w')# 以寫的方式開啟檔案,注意:如果此檔案不存在,則建立這個檔案;如果存在,則刪除原檔案所有內容
對於不同的檔案,有不同的處理方式,常用的mode引數如下:
模式描述 r讀 w寫 r+讀寫 w+寫讀 a追加 a+追加讀 rb二進位制讀 wb二進位制寫 rb+二進位制讀寫 wb+二進位制寫讀 ab二進位制追加 ab+二進位制追加讀
這些模式看似複雜,其實內部規律很清晰,接下來將用檔案的讀和寫來充分了解這些模式
2. 檔案的讀
read()「讀取檔案指標之後的所有內容,並返回字串」
這裡提到了一個新概念:檔案指標,想象一下,你在讀書,你的手指頭指著你正在讀的地方,你沒讀一個字,你的手指頭就跟著向後動一下,你的手指頭就是檔案指標,以上模式中,除了a、a+、ab+檔案指標在檔案末尾之外,其他的都是在檔案開頭
In [2]: f = open('再別康橋.txt')# 預設讀的方式開啟檔案 In [3]: f.read()# 讀取檔案指標之後的所有內容 Out[3]: '輕輕的我走了,\n正如我輕輕的來;\n我輕輕的招手,\n作別西天的雲彩。\n----\n那河畔的金柳,\n是夕陽中的新娘;\n波光裡的豔影,\n在我的心頭盪漾。\n----\n軟泥上的青荇,\n油油的在水底招搖;\n在康河的柔波里,\n我甘心做一條水草!\n----\n那榆蔭下的一潭,\n不是清泉,是天上虹;\n揉碎在浮藻間,\n沉澱著彩虹似的夢。\n----\n尋夢?撐一支長篙,\n向青草更青處漫溯;\n滿載一船星輝,\n在星輝斑斕裡放歌。\n----\n但我不能放歌,\n悄悄是別離的笙簫;\n夏蟲也為我沉默,\n沉默是今晚的康橋!\n----\n悄悄的我走了,\n正如我悄悄的來;\n我揮一揮衣袖,\n不帶走一片雲彩。\n'
In [9]: f = open('再別康橋.txt', 'w')# 以寫的模式開啟檔案,此時這個檔案的內容已經被刪除了:cold_sweat: In [10]: f.read()# 可以看到檔案是不允許讀的 --------------------------------------------------------------------------- UnsupportedOperationTraceback (most recent call last) <ipython-input-10-571e9fb02258> in <module> ----> 1 f.read() UnsupportedOperation: not readable
In [1]: f = open('test.jpg', 'rb')# 以二進位制方式開啟檔案 In [2]: f.read() Out[2]: b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00\xff\xdb\x00C\x00\x05\x04\x04\x05\x04\x03\x05\x05\x04\x05\x06\x06\...........' # 有許多檔案格式是以二進位制儲存的,最典型的就是圖片和視訊
readline()「讀一行」
In [1]: f = open('再別康橋.txt') In [2]: f.readline()# 讀一行 Out[2]: '輕輕的我走了,\n' In [3]: f.readline()# 再讀一行 Out[3]: '正如我輕輕的來;\n' In [4]: f.readline() Out[4]: '我輕輕的招手,\n' In [5]: f.readline() Out[5]: '作別西天的雲彩。\n'
readlines()「按行讀取檔案,將所有的行儲存為一個列表」
In [6]: f = open('再別康橋.txt') In [7]: f.readlines() Out[7]: ['輕輕的我走了,\n', '正如我輕輕的來;\n', '我輕輕的招手,\n', '作別西天的雲彩。\n', '----\n', '那河畔的金柳,\n', '是夕陽中的新娘;\n', '波光裡的豔影,\n', '在我的心頭盪漾。\n', '----\n', '軟泥上的青荇,\n', '油油的在水底招搖;\n', '在康河的柔波里,\n', '我甘心做一條水草!\n', '----\n', '那榆蔭下的一潭,\n', '不是清泉,是天上虹;\n', '揉碎在浮藻間,\n', '沉澱著彩虹似的夢。\n', '----\n', '尋夢?撐一支長篙,\n', '向青草更青處漫溯⑷;\n', '滿載一船星輝,\n', '在星輝斑斕裡放歌。\n', '----\n', '但我不能放歌,\n', '悄悄是別離的笙簫;\n', '夏蟲也為我沉默,\n', '沉默是今晚的康橋!\n', '----\n', '悄悄的我走了,\n', '正如我悄悄的來;\n', '我揮一揮衣袖,\n', '不帶走一片雲彩。\n']
檔案迭代「open函式開啟一個檔案後,這個控制代碼本身是可迭代物件」
In [8]: f = open('再別康橋.txt') In [9]: for line in f:# 直接迭代檔案 ...:print(line) ...: 輕輕的我走了, 正如我輕輕的來; 我輕輕的招手, 作別西天的雲彩。 ---- 那河畔的金柳, (將後面的輸出省略了)
3. 檔案的寫
write(text)「text表示要寫入檔案的內容,並返回寫入的字元數」
In [13]: f = open('new_file.txt', 'w')# 以寫的方式開啟檔案,如果檔案不存在則建立,如果存在則刪除原有內容 In [14]: f.write('hello')# 寫入hello Out[14]: 5 In [15]: f.write('word\n')# 寫入word並換行 Out[15]: 5
注意:如果這時候去檢視檔案內容,發現裡面還是空蕩蕩的,為什麼呢?因為寄存區快取的原因,預設是使用系統的寄存區快取機制,想要立刻寫入檔案可以改變buffering的值,也可以使用close()方法關閉檔案(關閉檔案時所有內容都會寫入檔案)、再或者使用flush()方法立即將寄存區內容寫入檔案
In [23]: f.flush()# 使用flush()方法立即刷入 In [24]: ! cat new_file.txt# 使用命令檢視檔案內容,檔案內容有兩行,一行字,一行空白(因為使用\n換行了),這個是Linux系統命令? helloword
In [25]: f = open('new_file.txt', 'a')# 以追加模式開啟,如果檔案存在則開啟檔案,如果不存在則新建檔案 In [27]: f.write('i am new\n') Out[27]: 9 In [28]: f.flush() In [30]: ! cat new_file.txt helloword i am new
In [31]: f = open('new_file.txt', 'a') In [32]: f.read()# 追加方式是不允許讀的,w、wb、ab也不允許讀 --------------------------------------------------------------------------- UnsupportedOperationTraceback (most recent call last) <ipython-input-32-571e9fb02258> in <module> ----> 1 f.read() UnsupportedOperation: not readable
In [33]: f = open('new_file.txt', 'a+')# 使用追加讀的方式開啟檔案 In [34]: f.read()# 可以讀,但為什麼是空的?因為檔案指標在末尾 Out[34]: '' In [36]: f.write('afd')# 也可以寫 Out[36]: 3
writelines(lines)「將一個列表或元組序列寫入檔案,需要換行自己加」
In [39]: f = open('new_file.txt', 'w') In [43]: f.writelines(['hello','world'])# 將列表序列寫入檔案 In [44]: f.writelines(('haha','hehe'))# 將元組序列寫入檔案 In [45]: f.flush()# 刷入 In [46]: ! cat new_file.txt# 檢視檔案內容 helloworldhahahehe
4. 關閉檔案
close()「關閉檔案,如果將寄存區有快取則寫入檔案」
In [48]: f.close()
5. 檔案其他方法
tell()「返回當前檔案指標位置」
seek(offset, whence=0)「offset代表要設定的檔案指標位置」
name「返回當前檔名」