1. 程式人生 > 其它 >Python 清空檔案以及檔案的讀寫

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)

,把檔案定位到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檔案的步驟

  1. 找到word文件
  2. 開啟word文件
  3. 檢視(或操作)word文件中的內容
  4. 關閉word文件

2) python操作txt檔案的步驟

  1. 獲取被開啟的檔案的記憶體物件,該記憶體物件又叫做“檔案控制代碼”。
  2. 通過這個記憶體物件(檔案控制代碼),來對檔案進行操作(讀取,寫入等操作)。
  3. 關閉檔案

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