文件讀寫與存儲
7.2. 讀寫文件
open()返回一個文件對象,最常見的用法帶有兩個參數:open(filename, mode)。
>>> f = open('workfile', 'w')
第一個參數是一個包含文件名的字符串。第二個參數是另一個包含幾個字符的字符串,用於描述文件的使用方式。mode為'r'
時表示只是讀取文件;w表示只是寫入文件(已經存在的同名文件將被刪掉);'a'
表示打開文件進行追加;寫入到文件中的任何數據將自動添加到末尾。'r+'
表示打開文件進行讀取和寫入。mode參數是可選的;如果省略,則默認為'r'
。
通常,文件以文本模式打開,它表示你從文件讀取以及向文件寫入的字符串是經過特定的編碼的。如果沒有指定編碼,則默認為與平台有關(參見open())。在mode后面附加'b'
將以二進制模式打開文件:現在數據以字節對象的形式讀取和寫入。這個模式應該用於所有不包含文本的文件。
在文本模式中,讀取的默認行為是將平台相關的換行(Unix上的\n
、Windows上的\r\n
)僅僅轉換為\n
。當在文本模式中寫入時,默認的行為是將\n
轉換為平台相關的換行。這種對文件數據的修改對文本文件沒有問題,但會損壞JPEG或EXE這樣的二進制文件中的數據。在讀取和寫入這樣的文件時要非常小心地使用二進制模式。
7.2.1. 文件對象的方法
本節中的示例將假設文件對象f
已經創建。
要讀取文件內容,可以調用f.read(size)
,該方法讀取若干數量的數據並以字符串(在文本模式中)或字節對象(在二進制模式中)形式返回它。size是一個可選的數值參數。當 size被省略或者為負數時,將會讀取並返回整個文件;如果文件大小是你機器內存的兩倍時,這會產生問題。否則,最多讀取並返回size字節。如果到了文件末尾,f.read()
會返回一個空字符串(" "
)。
例如:
文件名f.txt
This is the entire file.
vnfdgntgkhngh.
ngirg tng Hahaahahahahaha
vfnggoh
In [87]: f = open('f.txt')
In [88]: f.read()
Out[88]: 'This is the entire file.\nvnfdgntgkhngh.\nngirg tng Hahaahahahahaha\nvfnggoh'
In [89]: f.read()
Out[89]: ''
In [90]: f.close()
f.readline()
從文件讀取一行數據;字符串結尾會帶有一個換行符 (\n
) ,只有當文件最后一行沒有以換行符結尾時才會省略。這樣返回值就不會有混淆;如果f.readline()
返回一個空字符串,那就表示已經達到文件的末尾,而如果返回一個只包含一個換行符的字符串'\n'
,則表示遇到一個空行。
In [91]: f = open('f.txt')
In [92]: f.readline()
Out[92]: 'This is the entire file.\n'
In [93]: f.readline()
Out[93]: 'vnfdgntgkhngh.\n'
In [94]: f.readline()
Out[94]: 'ngirg tng Hahaahahahahaha\n'
In [95]: f.readline()
Out[95]: 'vfnggoh'
In [96]: f.readline()
Out[96]: ''
In [97]: f.close()
對於從文件中讀取行,可以在文件對象上循環。這是內存高效,快速,並導致簡單的代碼:
In [98]: f = open('f.txt')
In [99]: for line in f:
...: print(line, end='')
...:
This is the entire file.
vnfdgntgkhngh.
ngirg tng Hahaahahahahaha
vfnggoh
如果你想要讀取的文件列表中的所有行的數據,你也可以使用 list(f)
或 f.readlines()
。
f.write(string)
將 字符串 的內容寫入到該文件,返回寫入的字符數。
f.write(string) 將 字符串 的內容寫入到該文件,返回寫入的字符數。
In [105]: f = open('f.txt','a')
In [106]: f.write('This is test line.\n')
Out[106]: 19
其他類型的對象,在寫入之前則需要轉換成 字符串 (在文本模式下) 或 字節對象 (以二進制模式)
In [107]: value = ('the answer', 42)
In [108]: s = str(value) # convert the tuple to string
In [109]: f.write(s)
Out[109]: 18
f.tell()
返回一個整數,代表文件對象在文件中的當前的位置,在二進制模式中該數值表示自文件開頭到指針處的字節數,在文本模式中則是不准確的。
使用完一個文件后,調用f.close()可以關閉它並釋放其占用的所有系統資源。調用f.close()后,再嘗試使用該文件對象將自動失敗。
In [110]: f.close()
In [111]: f.read()
Traceback (most recent call last):
File "<ipython-input-111-571e9fb02258>", line 1, in <module>
f.read()
ValueError: I/O operation on closed file.
處理文件對象是使用with關鍵字是很好的做法。這具有的優點是,在其套件完成后,文件被正確關閉,即使在路上出現異常。它還比編寫一個等同的try-finally語句要短很多:
In [114]: with open('f.txt','r') as f:
...: read_data = f.read()
...: print(read_data)
...:
This is the entire file.
vnfdgntgkhngh.
ngirg tng Hahaahahahahaha
vfnggohThis is test line.
('the answer', 42)
In [115]: f.close()
補充實例:'r+'
表示打開文件進行讀取和寫入
In [124]: f = open('f.txt','r+')
In [125]: f.write('chj 2018-4-5')
Out[125]: 12
In [126]: f.write('AAABBBCCC')
Out[26]: 9
In [127]: f.close()
看看f.txt內容:
chj 2018-4-5AAABBBCCCle.
vnfdgntgkhngh.
ngirg tng Hahaahahahahaha
vfnggohThis is test line.
('the answer', 42)
7.2.2. 使用json存儲結構化數據
字符串可以輕松地寫入和讀取文件。數值就要多費點兒周折,因為read ()方法只會返回字符串,應將其傳入int()這樣的函數,就可以將'123'這樣的字符串轉換為對應的數值123。當您想要保存更復雜的數據類型(如嵌套列表和字典)時,手動解析和序列化變得復雜。
Python允許您使用名為JSON(JavaScript Object Notation)的流行數據交換格式,而不是讓用戶不斷地編寫和調試代碼以將復雜的數據類型保存到文件中。標准模塊json可以接受 Python 數據結構,並將它們轉換為字符串表示形式;此過程稱為序列化。從字符串表示重構數據稱為反序列化。在序列化和反序列化之間,表示對象的字符串可能已經存儲在文件或數據中,或者通過網絡連接發送到一些遠程機器。
注意JSON格式通常由現代應用程序使用以允許數據交換。許多程序員已經熟悉它,這使它成為互操作性的不錯選擇。