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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM