三步搞定 Python 中的檔案操作
當程式執行時,變數是儲存資料的好方法,但變數、序列以及物件中儲存的資料是暫時的,程式結束後就會丟失,如果希望程式結束後資料仍然保持,就需要將資料儲存到檔案中。
Python 提供了內建的檔案物件,以及對檔案、目錄進行操作的內建模組,通過這些技術可以很方便地將資料儲存到檔案(如文字檔案等)中。
一、檔案的概念
在計算機中,檔案是以二進位制的方式儲存在磁碟上的。
檔案分為文字檔案和二進位制檔案。
1、文字檔案
可以使用文字編輯軟體檢視,本質上還是二進位制檔案,例如:python 的源程式。
2、二進位制檔案
儲存的內容不是給人直接閱讀的,而是提供給其他軟體使用的。例如:圖片檔案、音訊檔案、視訊檔案等等,二進位制檔案不能使用文字編輯軟體檢視。
Python 中,對檔案的操作有很多種,常見的操作包括建立、刪除、修改許可權、讀取、寫入等,這些操作可大致分為以下 2 類:
- 刪除、修改許可權:作用於檔案本身,屬於系統級操作。
- 寫入、讀取:是檔案最常用的操作,作用於檔案的內容,屬於應用級操作。
二、檔案的基本操作
1、操作檔案的步驟
檔案的應用級操作可以分為以下 3 步,每一步都需要藉助對應的函式實現:
- 開啟檔案:使用 open() 函式,該函式會返回一個檔案物件;
- 對已開啟檔案做讀/寫操作:讀取檔案內容可使用 read()、readline() 以及 readlines() 函式;向檔案中寫入內容,可以使用 write() 函式。
- 關閉檔案:完成對檔案的讀/寫操作之後,最後需要關閉檔案,可以使用 close() 函式。
2、開啟檔案的方式
在 Python 中,如果想要操作檔案,首先需要建立或者開啟指定的檔案,並建立一個檔案物件,而這些工作可以通過內建的 open() 函式實現。
語法如下:
file = open(file_name [, mode='r' [ , buffering=-1 [ , encoding = None ]]])
- file:表示要建立的檔案物件。
- file_name:要建立或開啟檔案的檔名稱。
- mode:用於指定檔案的開啟模式。預設以只讀(r)模式開啟檔案。
- buffering:用於指定對檔案做讀寫操作時,是否使用緩衝區。
- encoding:手動設定開啟檔案時所使用的編碼格式,不同平臺的 ecoding 引數值也不同,以 Windows 為例,其預設為 cp936(實際上就是 GBK 編碼)。
開啟檔案的常用模式
模式 | 說明 |
---|---|
r | 以只讀方式開啟檔案。檔案的指標將會放在檔案的開頭,這是預設模式。如果檔案不存在,丟擲異常 |
w | 以只寫方式開啟檔案。如果檔案存在會被覆蓋。如果檔案不存在,建立新檔案 |
a | 以追加方式開啟檔案。如果該檔案已存在,檔案指標將會放在檔案的結尾。如果檔案不存在,建立新檔案進行寫入 |
r+ | 以讀寫方式開啟檔案。檔案的指標將會放在檔案的開頭。如果檔案不存在,丟擲異常 |
w+ | 以讀寫方式開啟檔案。如果檔案存在會被覆蓋。如果檔案不存在,建立新檔案 |
a+ | 以讀寫方式開啟檔案。如果該檔案已存在,檔案指標將會放在檔案的結尾。如果檔案不存在,建立新檔案進行寫入 |
open()是否需要緩衝區
通常情況下、建議大家在使用 open() 函式時開啟緩衝區,即不需要修改 buffing 引數的值。
如果 buffing 引數的值為 0(或者 False),則表示在開啟指定檔案時不使用緩衝區;如果 buffing 引數值為大於 1 的整數,該整數用於指定緩衝區的大小(單位是位元組);如果 buffing 引數的值為負數,則代表使用預設的緩衝區大小。
目前為止計算機記憶體的 I/O 速度仍遠遠高於計算機外設(例如鍵盤、滑鼠、硬碟等)的 I/O 速度,如果不使用緩衝區,則程式在執行 I/O 操作時,記憶體和外設就必須進行同步讀寫操作,也就是說,記憶體必須等待外設輸入(輸出)一個位元組之後,才能再次輸出(輸入)一個位元組。這意味著,記憶體中的程式大部分時間都處於等待狀態。
而如果使用緩衝區,則程式在執行輸出操作時,會先將所有資料都輸出到緩衝區中,然後繼續執行其它操作,緩衝區中的資料會有外設自行讀取處理;同樣,當程式執行輸入操作時,會先等外設將資料讀入緩衝區中,無需同外設做同步讀寫操作。
3、read 方法 —— 讀取檔案
read 方法可以一次性讀入並返回檔案的所有內容。
read() 函式的基本語法格式如下:
file.read([size])
其中,file 表示已開啟的檔案物件;size 作為一個可選引數,用於指定一次最多可讀取的字元(位元組)個數,如果省略,則預設一次性讀取所有內容。
如果忘記關閉檔案,會造成系統資源消耗,而且會影響到後續對檔案的訪問。
注意:read 方法執行後,會把檔案指標移動到檔案的末尾。
示例:
# 1. 開啟 - 檔名需要注意大小寫
file = open("README")
# 2. 讀取
text = file.read()
print(text)
# 3. 關閉
file.close()
在開發中,通常會先編寫開啟和關閉的程式碼,再編寫中間針對檔案的讀/寫操作!
4、按行讀取檔案內容
read 方法預設會把檔案的所有內容一次性讀取到記憶體。
如果檔案太大,對記憶體的佔用會非常嚴重。
readline 方法可以一次讀取一行內容,包含最後的換行符“\n”。方法執行後,會把檔案指標移動到下一行,準備再次讀取。
file.readline([size])
其中,file 為開啟的檔案物件;size 為可選引數,用於指定讀取每一行時,一次最多讀取的字元(位元組)數。
讀取大檔案的正確姿勢
# 開啟檔案
file = open("README")
while True:
# 讀取一行內容
text = file.readline()
# 判斷是否讀到內容
if not text:
break
# 每讀取一行的末尾已經有了一個 `\n`
print(text, end="")
# 關閉檔案
file.close()
示例:
小檔案複製
# 1. 開啟檔案
file_read = open("README")
file_write = open("README[復件]", "w")
# 2. 讀取並寫入檔案
text = file_read.read()
file_write.write(text)
# 3. 關閉檔案
file_read.close()
file_write.close()
大檔案複製
# 1. 開啟檔案
file_read = open("README")
file_write = open("README[復件]", "w")
# 2. 讀取並寫入檔案
while True:
# 每次讀取一行
text = file_read.readline()
# 判斷是否讀取到內容
if not text:
break
file_write.write(text)
# 3. 關閉檔案
file_read.close()
file_write.close()
對於按行來讀取檔案,還有一個 readlines() 函式。
readlines() 函式用於讀取檔案中的所有行,它和呼叫不指定 size 引數的 read() 函式類似,只不過該函式返回是一個字串列表,其中每個元素為檔案中的一行內容。
和 readline() 函式一樣,readlines() 函式在讀取每一行時,會連同行尾的換行符一塊讀取。
5、檔案指標
檔案指標可以理解為一個標記,它標記從哪個位置開始讀取資料。
第一次開啟檔案時,通常檔案指標會指向檔案的開始位置,當執行了 read 方法後,檔案指標預設情況下會移動到讀取內容的末尾。
如果執行了一次 read 方法,讀取了所有內容,那麼再次呼叫 read 方法,還能夠獲得到內容嗎?
答案是不能,第一次讀取之後,檔案指標移動到了檔案末尾,再次呼叫不會讀取到任何的內容。
# 首先在 README 檔案中寫了8個1
# 1. 開啟 - 檔名需要注意大小寫
file = open("README")
# 2. 讀取
text = file.read()
print(text)
text = file.read()
print("-" * 10)
print(text)
# 3. 關閉
file.close()
#1111111
#----------
#
6、向檔案中寫入資料
Python 中的檔案物件提供了 write() 函式,可以向檔案中寫入指定內容。該函式的語法格式如下:
file.write(string)
在寫入檔案完成後,一定要呼叫 close() 函式將開啟的檔案關閉,否則寫入的內容不會儲存到檔案中。
這是因為,當我們在寫入檔案內容時,作業系統不會立刻把資料寫入磁碟,而是先快取起來,只有呼叫 close() 函式時,作業系統才會保證把沒有寫入的資料全部寫入磁碟檔案中。
寫入檔案示例:
# 開啟檔案
f = open("README", "w")
f.write("hello python!\n")
f.write("今天天氣真好")
# 關閉檔案
f.close()
如果向檔案寫入資料後,不想馬上關閉檔案,也可以呼叫檔案物件提供的 flush() 函式,它可以實現將緩衝區的資料寫入檔案中。
f = open("a.txt", 'w')
f.write("寫入一行新資料")
f.flush()
三、檔案/目錄的常用管理操作
在終端 / 檔案瀏覽器中可以執行常規的檔案 / 目錄管理操作,例如:建立、重新命名、刪除、改變路徑、檢視目錄內容等等。
在 Python 中,如果希望通過程式實現上述功能,需要匯入 os 模組。
1、檔案操作
方法名 | 說明 | 示例 |
---|---|---|
rename | 重新命名檔案 | os.rename(原始檔名, 目標檔名) |
remove | 刪除檔案 | os.remove(檔名) |
2、目錄操作
方法名 | 說明 | 示例 |
---|---|---|
listdir | 目錄列表 | os.listdir(目錄名) |
mkdir | 建立目錄 | os.mkdir(目錄名) |
rmdir | 刪除目錄 | os.rmdir(目錄名) |
getcwd | 獲取當前目錄 | os.getcwd() |
chdir | 修改工作目錄 | os.chdir(目標目錄) |
path.isdir | 判斷是否是檔案 | os.path.isdir(檔案路徑) |
檔案或者目錄的操作都支援相對路徑和絕對路徑。