1. 程式人生 > 其它 >Python連載(0015): 檔案操作

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()

image-20210130172044675

注:觀察上面的執行結果,我們發現在這是第一行文字。----------之間多了一個空行,這是為什麼?f.readline()的時候,它讀取的這一行文字中本來就帶了一個換行符,而使用print()輸出時,該函式會預設在輸出的內容後面再加一個換行符,所以就導致多了一個空行。如果想要規避這個現象,可以將print(text)改成print(test, end="")。改完之後,程式執行結果如下:

image-20210130172542609

5. 追加模式

在之前建立的D:/test.txt中,追加一行本文。

# 以追加模式開啟檔案
f = open("D:/test.txt", "a")

# 向檔案中追加寫入一行資訊
f.write("這是一行追加的文字。\n")

# 關閉檔案,同時會對檔案進行儲存。
f.close()

執行完成後,D:/test.txt檔案內容如下:

image-20210130172914157

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()

執行結果如下:

image-20210130174033822

image-20210130174050845

從上面的結果我們可以發現,以r+模式開啟檔案後,執行讀操作時,它是從第一行開始讀;執行寫操作時,它是將新內容寫到檔案末尾。

可以這麼理解,當開啟一個檔案後,會有一個讀游標寫游標,分別對應讀操作和寫操作的位置。以r+模式開啟檔案後,讀游標位於檔案的起始處,而寫游標位於檔案的末尾。因此,讀操作會得到檔案的第一行,而寫入的內容會新增到檔案末尾。

7. 遍歷檔案

逐行讀取檔案的所有內容,並輸出。

# 開啟檔案
f = open("D:/test.txt", "r")

# 逐行讀取檔案
for line in f:
    print(line, end="")
    print("-"*10)

# 關閉檔案
f.close()

image-20210130173254460

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()

image-20210130182909604

9.2 readline()

readline()一次讀取檔案中的一行,以字串形式儲存。這種操作倒是記憶體損耗小,但是一次只能處理一行,所以會比較慢。

# 開啟檔案,指定'utf-8'編碼
f = open("D:/test.txt", "r", encoding = "utf-8")

# 讀取1行
text = f.readline()
print(text, end="")

# 關閉檔案
f.close()

image-20210130183155642

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()

image-20210130183509910

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()

image-20210130190011944

注意:name後面不要跟一對小括號()

9.11 fileno

返回檔案控制代碼在核心中的索引值,以後做IO多路複用時可以用到。

f = open("D:/test.txt", "r")
print("當前開啟的檔案是:{}".format(f.fileno))
f.close()

image-20210130190040943

注意:fileno後面不要跟一對小括號()