一:文件內容清空問題:
在工作中我們有時候還會清空文件中的內容 然后再重新寫入新的內容,哪如何清空已存文件的內容呢?
解決方法:
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),把文件定位到position 0,沒有這句的話,文件是定位到數據最后,truncate也是從這里刪除,所以感覺就是沒起作用。
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