Python 清空檔案以及檔案的讀寫
一:檔案內容清空問題:
在工作中我們有時候還會清空檔案中的內容 然後再重新寫入新的內容,哪如何清空已存檔案的內容呢?
解決方法:
def modify_text(): with open('test.txt', "r+") as f: read_data = f.read() f.truncate() #清空檔案 f.write(read_data.replace('apple', 'android'))
執行上面這個函式,它會把內容追加進去,而不是替換。
f.truncate()沒起作用,應該怎麼寫才可以呢?
需要加上f.seek(0)
def modify_text(): with open('test.txt', "r+") as f: read_data = f.read() f.seek(0) #定位 f.truncate() #清空檔案 f.write(read_data.replace('apple', 'android'))
-
f.seek(0):
把檔案定位到資料起始位置(index=0),若沒有這句的話,檔案則預設定位到資料結束位置,w.truncate()
-
w.truncate():
從**位置(index)**處清空檔案內容。
二:檔案讀寫的流程
2.1 類比windows中手動操作txt文件
說明python中如何操作txt檔案?
1)windows中手動操作txt檔案的步驟
- 找到word文件
- 開啟word文件
- 檢視(或操作)word文件中的內容
- 關閉word文件
2) python操作txt檔案的步驟
- 獲取被開啟的檔案的記憶體物件,該記憶體物件又叫做“檔案控制代碼”。
- 通過這個記憶體物件(檔案控制代碼),來對檔案進行操作(讀取,寫入等操作)。
- 關閉檔案
3)什麼是檔案的記憶體物件(檔案控制代碼)?
使用python讀取一個txt檔案的時候,相當於把這個檔案從硬碟上,讀取到了記憶體中。我們如果想要操作這個檔案,是不是先要獲取這個檔案物件?只有獲取這個檔案物件後,才能夠真正的去操作這個檔案,不管是讀取檔案中的內容,還是向檔案中寫入內容。
這個“檔案控制代碼”包含了檔案的檔名、檔案的字符集、檔案的大小、檔案在硬碟上的起始位置。
2.2 檔案的讀取
① 演示如下
import os def test_read_txt_01(): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) with open(file_path,'r+',encoding='utf-8') as f: data = f.read() data1 = f.read() print(data[:100]) print('========='*20) print(data1[:100]) if __name__ == '__main__': test_read_txt_01()
執行結果;
#執行結果: 使用python讀取一個txt檔案的時候, 相當於把這個檔案從硬碟上,讀取到了記憶體中。我們如果想要操作這個檔案,是不是先要獲取這個檔案物件? 只有獲取這個檔案物件後,才能夠真正的去操作這個檔案,不管是 ========================================================================= Process finished with exit code 0
問題:我們讀取了2遍內容,為什麼只顯示了一次讀取的結果呢?對於上述問題,我們用一張圖回答上述問題。
通過上圖我們可以發現,當我們操作這個“檔案控制代碼”的read()方法去讀取檔案的時候,這個控制代碼會從檔案的開頭位置1,移動到檔案的結束位置2。如果不做任何操作,讀取完畢之後,控制代碼就會停止在2這個位置。因此當我們再次讀取檔案的時候,該控制代碼是從2這個位置,往後面讀取內容。由於後面沒有任何內容,因此第二次讀取為空。
那麼,如果我們想要第二次同樣能夠讀取到檔案中的內容,應該怎麼辦呢?那麼接著往下看。
2.3寫入檔案
def test_write_text_01(data): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) with open(file_path, 'w', encoding='utf-8') as f: f.write(data) f.close() if __name__ == '__main__': test_write_text_01('第一次往text檔案寫入資料')
執行結果:
假如我們在寫一句“第二次寫入資料”,會出現啥情況呢?
def test_write_text_01(data): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) with open(file_path, 'w', encoding='utf-8') as f: f.write(data) f.close() if __name__ == '__main__': test_write_text_01('第二次寫入資料')
執行結果;
意外發生。當我們再次寫入新的內容的時候,發現之前寫的內容不見了,這是為啥呢?這就是我們下面要講述的“檔案讀寫的幾種常見模式”。
2.4 檔案讀寫的幾種常見模式
2.4.1)關於r+、w+、a+使用說明(易錯點)
當我們讀取某個檔案,向檔案中寫入某些內容(覆蓋寫),向檔案中追加寫入某寫內容時,最好的方式就是分別使用r、w、a這三種模式。對於這三種模式,要麼讀,要麼寫,讀模式就不能寫,寫模式就不能讀。
對於r+、w+、a+這三種模式,如果你不是特別清楚python檔案讀寫的原理,就不要輕易使用,因為會出現很多問題,下面我們僅演示r+、w+、a+這三種模式。
2.4.2)r+模式:可讀可寫
對於這種模式,不管是讀取檔案中的內容,還是朝檔案中寫入內容。前提條件:檔案存在,若檔案不存在 則會報錯。
def test_write_read_text_r_jia_01(): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) with open(file_path, 'r+',encoding='utf-8') as f: f.write('使用r加寫入資料') print('=====# 朝檔案中寫入內容後,立即讀取,會出現啥問題?===') data = f.read() print(f'讀取是的資料為:{data}') print('# 朝檔案中寫入內容後,調整控制代碼位置後,再讀取,會出現啥問題?') f.seek(0) data1 = f.read() print(f'讀取是的資料為:{data1}') if __name__ == '__main__': file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) f = open(file_path, 'r+',encoding='utf-8') data = f.read() print(f'讀取檔案原內容:{data}') print('===================') test_write_read_text_r_jia_01()
執行結果;
讀取檔案原內容:關於r+、w+、a+ =================== =====# 朝檔案中寫入內容後,立即讀取,會出現啥問題?=== 讀取是的資料為: # 朝檔案中寫入內容後,調整控制代碼位置後,再讀取,會出現啥問題? 讀取是的資料為:使用r加寫入資料 Process finished with exit code 0
結果分析:
使用r+模式,當只讀檔案的時候,可以讀取到其中的內容。
當寫入內容後,立即讀取檔案內容,發現什麼也讀取不到。這是由於當你寫入內容後,檔案控制代碼會放在寫入內容的最後面,因此當你立即讀取的時候,控制代碼會從上次內容最後的位置,朝後面讀,因此讀取為空。
當往檔案中寫入內容後,調整控制代碼位置後,再讀取檔案中的內容,發現就有了內容。這是由於我們使用了f.seek(0)方法,將控制代碼由內容末尾調整到了內容開頭,因此就又有了內容
2.4.3)w+:可讀可寫
def test_write_read_texy_w_jia_01(): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) # 直接往檔案中寫入內容 f = open(file_path, "w+", encoding="utf-8") f.write("bbbbbb") f.close()
print('========直接讀取上述檔案,看看會發生啥問題?==========\n') # 直接讀取上述檔案,看看會發生啥問題?(特別注意這一步) f = open(file_path, "w+", encoding="utf-8") data_1 = f.read() print(f'讀取資料data1:{data_1}\n') f.close() print('========朝檔案中寫入內容後,立即讀取,又會發生什麼?==========\n') # 朝檔案中寫入內容後,立即讀取,又會發生什麼? f = open(file_path, "w+", encoding="utf-8") f.write("哈哈哈哈哈") data_2 = f.read() print(f'讀取資料data_2:{data_2}\n') f.close() print('========朝檔案中寫入內容後,調整控制代碼位置後,再讀取,會發生什麼?==========\n') # 朝檔案中寫入內容後,調整控制代碼位置後,再讀取,會發生什麼? f = open(file_path, "w+", encoding="utf-8") f.write("嘿嘿嘿嘿嘿") f.seek(0) data_3 = f.read() print(f'讀取資料data_2:{data_3}\n') f.close() if __name__ == '__main__': test_write_read_texy_w_jia_01()
執行結果:
========直接讀取上述檔案,看看會發生啥問題?========== 讀取資料data1: ========朝檔案中寫入內容後,立即讀取,又會發生什麼?========== 讀取資料data_2: ========朝檔案中寫入內容後,調整控制代碼位置後,再讀取,會發生什麼?========== 讀取資料data_2:嘿嘿嘿嘿嘿 Process finished with exit code 0
結果分析:
使用w+模式,當我們直接朝檔案中寫入bbbbbb,毋庸置疑,肯定是可以的。
接著,我們直接讀取這個檔案中的內容,奇怪的現象發生了,什麼都讀取不到。這是因為w+模式,在進行檔案讀取的時候,預設是先寫再讀。但是我們確實沒有寫入任何東西呀?這是由於系統預設幫我們寫入了一個空值,因此把原有內容覆蓋了。所以再當我們讀取檔案中的內容的時候,發現讀取為空。
再接著,我們朝檔案中,寫入內容後再立即讀取,這下仍然讀取不到任何內容,這又是為什麼呢?這是由於我們第一次寫入“哈哈哈哈哈哈”的時候,控制代碼移動到了內容最後。當我們立即讀取的時候,控制代碼從內容最後的位置,繼續朝後面讀,因此啥也沒有。
最後,當朝檔案中寫入內容後,調整控制代碼位置後,再讀取檔案中的內容,發現就有了內容。這是由於我們使用了f.seek(0)方法,將控制代碼由內容末尾調整到了內容開頭,因此就又有了內容。
2.4.4)a+:可讀可寫
def text_wire_read_txt_a_jia_01(): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) # 直接朝檔案中寫入內容 f = open(file_path, "a+", encoding="utf-8") f.write("哈哈") f.close() print('========直接讀取檔案中的內容==========\n') # 直接讀取檔案中的內容 f = open(file_path, "a+", encoding="utf-8") data_1 = f.read() print(f'讀取資料data_2:{data_1}\n') f.close() print('========調整控制代碼位置後,再讀取檔案中的內容==========\n') # 調整控制代碼位置後,再讀取檔案中的內容 f = open(file_path, "a+", encoding="utf-8") f.seek(0) data_2 = f.read() print(f'讀取資料data_2:{data_2}\n') f.close() if __name__ == '__main__': text_wire_read_txt_a_jia_01()
執行結果:
========直接讀取檔案中的內容========== 讀取資料data_2: ========調整控制代碼位置後,再讀取檔案中的內容========== 讀取資料data_2:嘿嘿嘿嘿嘿哈哈 Process finished with exit code 0
結果分析:
使用a+模式,朝檔案中寫入內容,會接著原有的內容繼續追加內容,毋庸置疑,肯定是沒問題的。
接著,當我們讀取上述檔案中的內容,會發現什麼也讀取不到。這是由於,使用a+模式開啟檔案,檔案控制代碼預設放在內容的最後面,因此你直接讀取其中的內容,什麼也沒有。
最後,在讀取檔案中內容之前,我們使用了f.seek(0)方法,將控制代碼由內容末尾調整到了內容開頭,再次讀取檔案中的內容,發現就有了內容。
2.5 read、readline、readlines的區別
2.5.1)read()方法的使用
def test_read(): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) f = open(file_path, "r", encoding="utf-8") data = f.read() print(type(data)) print(data) f.close() if __name__ == '__main__': test_read()
執行結果:
<class 'str'> 君不見黃河之水天上來,奔流到海不復回 君不見高堂明鏡悲白髮,朝如青絲暮成雪 人生得意須盡歡,莫使金樽空對月 天生我材必有用,千金散盡還復來 Process finished with exit code 0
2.5.2)readline()方法的使用
def test_readline(): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) f = open(file_path, "r", encoding="utf-8") data = f.readline() print(type(data)) print(data) f.close() print('========================') f = open(file_path, "r", encoding="utf-8") for i in range(3): data = f.readline() print(data) f.close() print('==========去掉每一行末尾的換行符==============\n') #去掉每一行末尾的換行符: f = open(file_path, "r", encoding="utf-8") for i in range(3): data = f.readline().strip() print(data) f.close() if __name__ == '__main__': test_readline()
執行結果:
2.5.3)readlines()方法的使用
def test_readlines(): file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) f = open(file_path, "r", encoding="utf-8") data = f.readlines() print(type(data)) print(data) f.close() if __name__ == '__main__': test_readlines()
執行結果:
2.6 對於一個10G的大檔案,怎麼高效的檢視檔案中的內容呢?
2.6.1)相關說明
當我們讀取檔案中的內容,相當於是把寫在硬碟上的東西,讀取到記憶體中。不管你是使用read()或者readlines()一次性讀取到到記憶體中,還是使用readline()一行行的將整個內容讀取到記憶體中,如果檔案很大,都將會耗用很大的記憶體。同時,從硬碟讀取檔案內容到記憶體中,也會很慢。
因此,有沒有一種高效的方式?既讓我們看到了檔案中的內容,又不會佔用記憶體呢?下面我們將進行說明。
2.6.2)操作說明
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.txt')) f = open(file_path ,"r",encoding="utf-8") for line in f: print(line.strip())
執行結果:
結果說明:
上述方式中,f相當於一個迭代器,我們使用for迴圈迭代f中元素。每迴圈一次,就相當於讀取一行到記憶體中,並記住這一次讀取到的位置。當進行下次迭代的時候,上一次讀取到記憶體中的內容,就會被銷燬了,當前記憶體中讀取的就是第二行的內容。當進行第三次迴圈的時候,記憶體中第二行的內容也會被銷燬,此時記憶體中只會儲存第三行的內容,這樣依次進行下去。直到最後一次迴圈,讀取最後一行的內容,此時,記憶體中保留的也只是最後一行的內容。
迭代器有一個特性:每次進行迭代的時候,就會記住當前讀取的位置。當進行下一次迭代的時候,前面的內容會被銷燬掉,在記憶體中只會保留當前迴圈得到的內容。
原文連結:https://blog.csdn.net/weixin_41261833/article/details/104462907