Python連載(0015): 檔案操作
技術標籤:# 老王的Python筆記python
文章目錄
1. 前言
我們平時操作文字檔案的時候,基本上都是按照如下步驟:
- 建立新檔案或者開啟已有檔案
- 讀或者修改檔案內容
- 儲存檔案並關閉
用Python操作檔案的基本步驟也是類似的,Python提供了檔案建立、開啟、讀、寫、儲存、關閉等介面函式供使用者使用。今天老王就來整理一下這些介面函式的使用方法。
2. 操作模式
在開啟檔案的時候,需要指定對檔案的操作模式。比如,以只讀模式開啟或者以寫入模式開啟等等。Python支援多種操作模式,功能如下:
-
r模式(只讀模式)
開啟檔案後,只能讀取檔案內容,不能修改。
-
w模式(寫入模式)
如果要操作的檔案不存在,那麼會建立一個新檔案。
如果要操作的檔案存在,那麼新寫入的內容會覆蓋檔案中原有的內容。
-
a模式(追加模式)
以該模式開啟檔案後,新寫入的內容會被新增到檔案末尾,不會覆蓋檔案中的原有內容
如果檔案不存在,那麼會建立一個新檔案。
-
w+模式(寫讀模式)
這個模式老王沒怎麼用到過,它在w模式的基礎上,添加了讀許可權。也就是說,以w+模式開啟檔案之後,你向檔案寫了一部分內容,然後在不用重新開啟檔案的情況下,你接著就可以把剛才寫的內容讀出來。
-
r+模式(讀寫模式)
能讀能寫,寫入的內容都被新增到檔案最後。
-
a+模式(追加讀模式)
檔案開啟之後,游標就會在檔案末尾,寫入的資料全部新增到檔案最後。
3. 建立檔案
需求:
- 在
D:
建立一個名為test.txt
文字檔案。 - 向檔案中寫入一些內容
- 儲存並關閉檔案。
# 以寫模式開啟檔案,鑑於當前D盤下沒有test.txt檔案,所以它會建立該檔案。
f = open("D:/test.txt", "w")
# 也可以寫成: f = open(file = "D:/test.txt", mode = "w")
# 向檔案中寫入一行資訊
f.write("這是第1行文字。\n")
f.write("這是第2行文字。\n")
f.write("這是第3行文字。\n")
f.write("這是第4行文字。\n")
# 關閉檔案,同時會對檔案進行儲存。
f.close()
4. 只讀模式操作檔案
# 開啟已經存在的檔案
f = open(file = "D:/test.txt", mode = "r")
# 讀1行,並輸出
text = f.readline()
print(text)
print("-"*10) # 輸出一串字元進行分隔
# 讀取剩下的所有內容
text = f.read()
print(text)
# 關閉檔案
f.close()
注:觀察上面的執行結果,我們發現在這是第一行文字。
和----------
之間多了一個空行,這是為什麼?f.readline()
的時候,它讀取的這一行文字中本來就帶了一個換行符,而使用print()
輸出時,該函式會預設在輸出的內容後面再加一個換行符,所以就導致多了一個空行。如果想要規避這個現象,可以將print(text)
改成print(test, end="")
。改完之後,程式執行結果如下:
5. 追加模式
在之前建立的D:/test.txt
中,追加一行本文。
# 以追加模式開啟檔案
f = open("D:/test.txt", "a")
# 向檔案中追加寫入一行資訊
f.write("這是一行追加的文字。\n")
# 關閉檔案,同時會對檔案進行儲存。
f.close()
執行完成後,D:/test.txt
檔案內容如下:
6. r+模式
假設當前D:/test.txt
檔案的內容如下:
這是第1行文字。
這是第2行文字。
這是第3行文字。
這是第4行文字。
然後執行如下程式碼:
# 以r+模式開啟檔案
f = open("D:/test.txt", "r+")
# 讀取1行
text = f.readline()
print(text)
# 寫入1行資訊
f.write("這是為了驗證r+模式寫入的文字。")
# 關閉並儲存檔案
f.close()
執行結果如下:
從上面的結果我們可以發現,以r+
模式開啟檔案後,執行讀操作時,它是從第一行開始讀;執行寫操作時,它是將新內容寫到檔案末尾。
可以這麼理解,當開啟一個檔案後,會有一個讀游標
和寫游標
,分別對應讀操作和寫操作的位置。以r+
模式開啟檔案後,讀游標
位於檔案的起始處,而寫游標
位於檔案的末尾。因此,讀操作會得到檔案的第一行,而寫入的內容會新增到檔案末尾。
7. 遍歷檔案
逐行讀取檔案的所有內容,並輸出。
# 開啟檔案
f = open("D:/test.txt", "r")
# 逐行讀取檔案
for line in f:
print(line, end="")
print("-"*10)
# 關閉檔案
f.close()
8. 指定檔案編碼
在開啟檔案的時候,可以指定以哪種檔案編碼格式開啟檔案,用法如下:
# 以寫模式開啟檔案,指定'utf-8'編碼
f = open("D:/test.txt", "w", encoding = "utf-8")
# 向檔案中寫入一行資訊
f.write("這是第1行文字。\n")
f.write("這是第2行文字。\n")
f.write("這是第3行文字。\n")
f.write("這是第4行文字。\n")
# 關閉檔案,同時會對檔案進行儲存。
f.close()
# 開啟檔案,指定'utf-8'編碼
f = open("D:/test.txt", "r", encoding = "utf-8")
# 逐行讀取檔案
for line in f:
print(line, end="")
print("-"*10)
# 關閉檔案
f.close()
9. 其他功能
9.1 read()
read()
可以一次將整個檔案的內容讀取出來,放到一個字串中。這種操作有一個缺點,如果檔案非常大時會很耗記憶體。
# 開啟檔案,指定'utf-8'編碼
f = open("D:/test.txt", "r", encoding = "utf-8")
# 讀取全部檔案
text = f.read()
print(text, end="")
# 關閉檔案
f.close()
9.2 readline()
readline()
一次讀取檔案中的一行,以字串形式儲存。這種操作倒是記憶體損耗小,但是一次只能處理一行,所以會比較慢。
# 開啟檔案,指定'utf-8'編碼
f = open("D:/test.txt", "r", encoding = "utf-8")
# 讀取1行
text = f.readline()
print(text, end="")
# 關閉檔案
f.close()
9.3 readlines()
readlines()
一次讀取整個檔案,並儲存成一個列表,檔案的每一行成為列表的一個元素。
缺點和read()
一樣,讀取大檔案的時候耗記憶體。
# 開啟檔案,指定'utf-8'編碼
f = open("D:/test.txt", "r", encoding = "utf-8")
# 讀取所有文字
text = f.readlines()
print(text)
print("-"*10)
print(text[0], end="")
print(text[1], end="")
print(text[2], end="")
# 關閉檔案
f.close()
9.4 flush()
程式碼對檔案進行操作,在執行f.close()
之前,對檔案的修改其實都是在記憶體中進行的,這時候還沒有儲存到硬碟上。如果執行f.close()
之前停電了,那對檔案的修改是無法生效的,再開機之後就會發現檔案並沒有被修改。
flush()
就是主動將記憶體中對檔案的修改寫入到硬碟中,避免系統奔潰或者斷電時來不及儲存。
# 以寫模式開啟檔案
f = open("D:/test.txt", "w")
# 向檔案中寫入一行資訊
f.write("這是第1行文字。\n")
f.flush() # 重新整理硬碟
f.write("這是第2行文字。\n")
f.flush() # 重新整理硬碟
f.write("這是第3行文字。\n")
f.flush() # 重新整理硬碟
f.write("這是第4行文字。\n")
# 關閉檔案,同時會對檔案進行儲存。
f.close()
注:flush()
會引入硬碟寫入,而硬碟的寫入操作比記憶體要慢N倍,所以頻繁flush()
會導致程式效率降低。
9.5 seek()
我們知道,在訪問檔案時,會有一個游標指示當前在操作檔案的哪個位置,如果在開啟檔案後直接將游標移動到指定位置,可以使用seek()
。
seek()
的長度是按照位元組算的,而不同的編碼方式又導致每個字元所佔的字元長度不一樣。
如恭喜發財
四個漢字,在GBK編碼下,一個漢字佔2個位元組,此時seek(4)
就能把游標切換到喜
和發
兩個字中間。但在utf-8編碼下,一個漢字佔3個位元組,此時seek(4)
就只能拿到喜
字的一部分,輸出的時候就會報錯。
9.6 tell()
tell()
用於返回當前游標的位置,也是以位元組為單位。
9.7 readable() & writable() & seekable()
readable()
用於判定當前是否對檔案具有讀許可權。
writable()
用於判定當前是否對檔案具有寫許可權。
seekable()
用於判定當前是否對檔案具有seek許可權。
9.10 name
獲取當前檔案的檔名。
f = open("D:/test.txt", "r")
print("當前開啟的檔案是:{}".format(f.name))
f.close()
注意:name
後面不要跟一對小括號()
。
9.11 fileno
返回檔案控制代碼在核心中的索引值,以後做IO多路複用時可以用到。
f = open("D:/test.txt", "r")
print("當前開啟的檔案是:{}".format(f.fileno))
f.close()
注意:fileno
後面不要跟一對小括號()
。