1. 程式人生 > >記錄我的 python 學習歷程-Day08 檔案的操作

記錄我的 python 學習歷程-Day08 檔案的操作

檔案操作的初識

  • 用 python 程式碼對檔案進行各種操作。

    基本構成:

    • 檔案路徑:path
    • 開啟方式:讀、寫、追加、讀寫、寫讀……
    • 編碼方式:utf-8 / gbk / gb2312……
    f = open('檔案路徑或者相對路',encoding='編碼方式',mode='模式') # 格式構成
    cotent = f.read()
    print(content)
    f.close()
  • 程式碼解釋:

    • open:

      ​ 內建函式,open 底層呼叫的是作業系統的介面。

    • f:

      ​ 變數,約定俗成的變數名有(f1,fh,file_handler,f_h),這個變數還有一個名字,叫檔案控制代碼。對亠件進行的任何操作,都得通過檔案控制代碼加'.'的方式。

    • encoding:

      ​ 可以不寫,如果不寫,預設的編碼本就是系統預設的編碼。

      ​ Windows: gkb

      ​ Linux: utf-8

      ​ MacOS: utf-8

    • mode:

      ​ 就是定義你的操作方式:r 為讀模式。

    • f.read():

      ​ 你想操作檔案,比如讀檔案,給檔案寫內容,等等,都必須通過檔案控制代碼進行操作。

    • f.colse():

      ​ 關閉檔案。(必須關閉,否則會常駐記憶體。)

  • 檔案操作的三個步驟:

    • 開啟檔案。

    • 對檔案控制代碼進行相應的操作。

    • 關閉檔案。

      # 開啟檔案,得到檔案控制代碼並賦值給一個變數
      f = open('檔案.txt', 'r', encoding='utf-8')   # 預設開啟模式就為 r
      
      # 通過控制代碼對檔案進行操作
      date = f.read()
      
      # 關閉檔案
      f.close()
  • 報錯的原因:

    • UnicodeDecodeError:檔案儲存時與檔案開啟時編碼本不一致。

    • 路徑分隔符產生的問題:

      解決方法:在路徑前加個 r
      r'C:\Users\Desktop\檔案.txt'

檔案操作的:讀

​ 檔案操作的讀,有四種模式(r、rb、r+、r+b),r+ 和 r+b 不常用, rb 操作的是非文字的檔案,比如:圖片、視訊、音訊。每種模式有五種方法(read()、read(n)、readline()、readlines()、for)。

  • r 模式

    ​ 以只讀方式開啟檔案,檔案的指標將會放在檔案的開頭。是檔案操作最常用的模式,也是預設模式,如果一個檔案不設定mode,那麼預設使用r模式操作檔案。

    舉例:

    f = open('檔案.txt', mode='r', encoding='utf-8')
    msg = f.read()
    f.close()
    print(msg)
    • read() 一次性全部讀取

      read() 將檔案中的內容全部讀取出來; 弊端:如果檔案很大就會非常的佔用記憶體,容易導致記憶體崩潰。

      f = open('測試', mode='r', encoding='utf-8')
      msg = f.read()
      f.close()
      print(msg)
      
      # 輸出結果:
      這是一行測試
      A:這是第二行
      B:這是第三行
      C:這是第幾行
      D:這是我也不知道第幾行
      就這麼地吧.
    • read(n) 指定讀取到什麼位置

      在 r 模式下,n 按照字元讀取

      f = open('測試', mode='r', encoding='utf-8')
      msg = f.read(4)
      f.close()
      print(msg)
      
      # 輸出結果:
      這是一行
    • readline() 按行讀取

      readline() 每次只讀取一行,注意: readline() 讀取出來的資料在後面都有一個\n,解決這個問題只需要在我們讀取出來的檔案後邊加一個strip()就OK了

      f = open('測試', mode='r', encoding='utf-8')
      msg1 = f.readline()
      msg2 = f.readline().strip()
      msg3 = f.readline()
      msg4 = f.readline()
      f.close()
      print(msg1)
      print(msg2)
      print(msg3)
      print(msg4)
      
      # 輸出結果:
      這是一行測試
      
      A:這是第二行
      B:這是第三行
      
      C:這是第幾行
      
    • readlines() 返回一個列表

      readlines() 返回一個列表,列表裡面每個元素是原檔案的每一行,如果檔案很大,佔記憶體,容易崩盤。

      f = open('測試', mode='r', encoding='utf-8')
      print(f.readlines())    # 還可以這麼寫的,哈哈
      f.close()
      
      # 輸出結果:
      ['這是一行測試\n', 'A:這是第二行\n', 'B:這是第三行\n', 'C:這是第幾行\n', 'D:這是我也不知道第幾行\n', '就這麼地吧.']

    上面這四種都不太好,如果檔案超大,內容超多,他們就很容易將記憶體撐爆,所以,我們還有第五種方法。

    • for 迴圈

      可以通過for迴圈去讀取,檔案控制代碼是一個迭代器,他的特點就是每次迴圈只在記憶體中佔一行的資料,非常節省記憶體。

      f = open('測試', mode='r', encoding='utf-8')
      for line in f:
          print(line)     # 去掉 \n 可以這樣寫: print(line.strip())  
      # 這種方式就是在一行一行的進行讀取,它就執行了下邊的功能
      
      '''
      print(f.readline())
      print(f.readline())
      print(f.readline())
      .......
      '''
      # 輸出結果:
      這是一行測試
      
      A:這是第二行
      
      B:這是第三行
      
      C:這是第幾行
      
      D:這是我也不知道第幾行
      
      就這麼地吧.
      

    特別注意: 讀完的檔案一定必須要關閉

  • rb 模式

    rb模式:以二進位制格式開啟一個檔案用於只讀。檔案指標將會放在檔案的開頭。記住下面講的也是一樣,帶b的都是以二進位制的格式操作檔案,他們主要是操作非文字檔案:圖片,音訊,視訊等,並且如果你要是帶有b的模式操作檔案,那麼不用宣告編碼方式。

    f1 = open('圖片.jpeg', mode='rb')
    tu = f1.read()
    f1.close()
    print(tu)
    
    # 輸出結果:
    b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00H\x00H\x00\x00\xff\xe1\x00\xb0Exif\x............後面還有.老長老長了..此處省略了.

    rb模式也有read read(n) readline(),readlines() for迴圈這幾種方法,這裡就不一一演示了。

檔案操作的:寫

​ 檔案操作的寫,有四種模式(w、wb、w+、w+b),w+ 和 w+b 不常用, wb 操作的是非文字的檔案,比如:圖片、視訊、音訊。操作方法是:write('要寫入的內容')

  • w 模式

    如果檔案不存在,用 w 模式操作檔案,它會先建立檔案,然後寫入內容。

    f = open('這是一個新建立的檔案', encoding='utf-8', mode='w')
    f.write('果然是一個新建立的檔案')
    f.close()

    如果檔案存在,利用w模式操作檔案,先清空原檔案內容,在寫入新內容。

    f = open('這是一個新建立的檔案', encoding='utf-8', mode='w')
    f.write('這是清空後重新寫入的內容')
    f.close()
  • wb 模式

    wb模式:以二進位制格式開啟一個檔案只用於寫入。如果該檔案已存在則開啟檔案,並從開頭開始編輯,即原有內容會被刪除。如果該檔案不存在,建立新檔案。一般用於非文字檔案如:圖片,音訊,視訊等。

    >>舉個例子 :

    我先以rb的模式將一個圖片的內容以bytes型別全部讀取出來,然後在以wb將全部讀取出來的資料寫入一個新檔案,這樣我就完成了類似於一個圖片複製的流程。具體程式碼如下:

    # 第一步:將原圖片通過 rb 模式讀取出來。
    f = open('圖片.jpeg', mode='rb')
    content = f.read()
    f.close()
    # 第二步:將讀取出來的資料通過 wb 模式寫入新檔案。
    f1 = open('圖片1.jpeg', mode='wb')
    f1.write(content)
    f1.close()

檔案操作的:追加

就是在檔案中追加內容。這裡也有四種檔案分類主要四種模式:a,ab,a+,a+b,我們只講a

  • a 模式

    如果檔案不存在,利用a模式操作檔案,那麼它會先建立檔案,然後寫入內容。

    f = open('追加文字', encoding='utf-8', mode='a')
    f.write('這個檔案是沒有的,我是新建立的')
    f.close()

    如果檔案存在,利用a模式操作檔案,那麼它會在檔案的最後面追加內容。

    f = open('追加文字', encoding='utf-8', mode='a')
    f.write('這是己存在的檔案,我是新追加的內容')
    f.close()

檔案操作的其它模式

​ 咱們還有一種模式沒有講,就是那種帶+號的模式。什麼是帶+的模式呢?+就是加一個功能。比如剛才講的r模式是隻讀模式,在這種模式下,檔案控制代碼只能進行類似於read的這讀的操作,而不能進行write這種寫的操作。所以我們想讓這個檔案控制代碼既可以進行讀的操作,又可以進行寫的操作,那麼這個如何做呢?這就是接下來要說這樣的模式:r+ 讀寫模式,w+寫讀模式,a+寫讀模式,r+b 以bytes型別的讀寫模式.........
在這裡咱們只講一種就是r+,其他的大同小異,自己可以練練就行了。

#1. 開啟檔案的模式有(預設為文字模式):
r,只讀模式【預設模式,檔案必須存在,不存在則丟擲異常】
w,只寫模式【不可讀;不存在則建立;存在則清空內容】
a, 只追加寫模式【不可讀;不存在則建立;存在則只追加內容】

#2. 對於非文字檔案,我們只能使用b模式,"b"表示以位元組的方式操作(而所有檔案也都是以位元組的形式儲存的,使用這種模式無需考慮文字檔案的字元編碼、圖片檔案的jgp格式、視訊檔案的avi格式)
rb 
wb
ab
注:以b方式開啟時,讀取到的內容是位元組型別,寫入時也需要提供位元組型別,不能指定編碼

#3,‘+’模式(就是增加了一個功能)
r+,讀寫【可讀,可寫】
w+,寫讀【可寫,可讀】
a+,寫讀【可寫,可讀】

#4,以bytes型別操作的讀寫,寫讀,寫讀模式
r+b,讀寫【可讀,可寫】
w+b,寫讀【可寫,可讀】
a+b,寫讀【可寫,可讀】
  • r+ 模式 讀並追加 順序不能錯

    r+: 開啟一個檔案用於讀寫。檔案指標預設將會放在檔案的開頭。

    f = open('檔案的讀寫.txt', encoding='utf-8', mode='r+')
    content = f.read()
    print(content)
    f.write('這是新寫入的內容')
    f.close()

      注意:如果你在讀寫模式下,先寫後讀,那麼檔案就會出問題,因為預設游標是在檔案的最開始,你要是先寫,則寫入的內容會講原內容覆蓋掉,直到覆蓋到你寫完的內容,然後在後面開始讀取。

小總結:

三個大方向:
​ 讀, 四種模式: r rb r+ r+b
​ 寫, 四種模式 : w,wb, w+,w+b
​ 追加 四種模式: a, ab, a+,a+b

相應的功能:
​ 對檔案控制代碼的操作:read read(n) readline() readlines() write()

檔案操作的其它功能

  • f.tell() 獲取游標的位置 單位是:位元組

    f = open('測試', encoding='utf-8', mode='r')
    print(f.tell())
    content = f.read()
    print(f.tell())
    f.close()
    
    # 原檔案內容
    這是一行測試
    A:這是第二行
    B:這是第三行
    C:這是第幾行
    D:這是我也不知道第幾行
    就這麼地吧.
    
    # 輸出結果:
    0   # 開始的位置
    122 # 結束的位置
  • f.seek() 調整游標的位置 (注意:移動單位是byte , 如果是utf-8的中文部分要是3的倍數)

    f = open('測試', encoding='utf-8', mode='r')
    f.seek(9)
    content = f.read()
    print(content)
    f.close()
    
    # 原檔案內容
    這是一行測試
    A:這是第二行
    B:這是第三行
    C:這是第幾行
    D:這是我也不知道第幾行
    就這麼地吧.
    
    # 輸出結果:
    行測試
    A:這是第二行
    B:這是第三行
    C:這是第幾行
    D:這是我也不知道第幾行
    就這麼地吧.
  • f.flush() 強制重新整理

    f = open('測試', encoding='utf-8', mode='w')
    f.write('fafdsfsfsadfsaf')
    f.flush()
    f.close()

開啟檔案的另一種方式(常用的是這種)

  • with open() as ....

    # 優點1:不用手動關閉檔案控制代碼
    # 利用with上下文管理這種方式,它會自動關閉檔案控制代碼。
    with open('測試', encoding='utf-8', mode='r') as f:
        print(f.read())
    
    # 優點2:可以加多個 open 操作
    # 一個with 語句可以操作多個檔案,產生多個檔案控制代碼。
    with open('測試', encoding='utf-8', mode='r') as f,\
            open('測試', encoding='utf-8', mode='w') as f1:
        print(f.read())
        f1.write('kckckckckckckkck')

      這裡要注意一個問題,雖然使用with語句方式開啟檔案,不用你手動關閉檔案控制代碼,比較省事兒,但是依靠其自動關閉檔案控制代碼,是有一段時間的,這個時間不固定,所以這裡就會產生問題,如果你在with語句中通過r模式開啟t1檔案,那麼你在下面又以a模式開啟t1檔案,此時有可能你第二次開啟t1檔案時,第一次的檔案控制代碼還沒有關閉掉,可能就會出現錯誤,他的解決方式只能在你第二次開啟此檔案前,手動關閉上一個檔案控制代碼。

檔案的修改

​ 檔案的資料是存放於硬碟上的,因而只存在覆蓋、不存在修改這麼一說,我們平時看到的修改檔案,都是模擬出來的效果,具體的說有兩種實現方式:

  • 檔案操作改的流程:
    1,以讀的模式開啟原檔案。
    2,以寫的模式建立一個新檔案。
    3,將原檔案的內容讀出來修改成新內容,寫入新檔案。
    4,將原檔案刪除。
    5,將新檔案重新命名成原檔案。

  • 方式一:將硬碟存放的該檔案的內容全部載入到記憶體,在記憶體中是可以修改的,修改完畢後,再由記憶體覆蓋到硬碟(word,vim,nodpad++等編輯器)

    import os   # 呼叫系統模組
    with open('測試', encoding='utf-8') as f1,\
        open('測試.bak', encoding='utf-8',mode='w') as f2:
        old_content = f1.read() # 全部讀入記憶體,如果檔案很大,會卡死
        new_content = old_content.replace('文', 'wen')   # 在記憶體中完成修改
        f2.write(new_content)   # 一次性寫入新檔案
    os.remove('測試') # 刪除原檔案
    os.rename('測試.bak', '測試')   # 將新建的檔案重新命名為原檔案
    
    # 原檔案內容
    **檔案操作改的流程:**
    1,以讀的模式開啟原檔案。
    2,以寫的模式建立一個新檔案。
    3,將原檔案的內容讀出來修改成新內容,寫入新檔案。
    4,將原檔案刪除。
    5,將新檔案重新命名成原檔案。
    # 修改後的內容
    **wen件操作改的流程:**
    1,以讀的模式開啟原wen件。
    2,以寫的模式建立一個新wen件。
    3,將原wen件的內容讀出來修改成新內容,寫入新wen件。
    4,將原wen件刪除。
    5,將新wen件重新命名成原wen件。
  • 方式二:將硬碟存放的該檔案的內容一行一行地讀入記憶體,修改完畢就寫入新檔案,最後用新檔案覆蓋原始檔(這種是常用的)

    import os
    with open('測試', encoding='utf-8') as f1,\
        open('測試.bak', encoding='utf-8',mode='w') as f2:
        for line in f1: # 一行一行的改,佔記憶體少
            new_line = line.replace('wen', '文')
            f2.write(new_line)
    os.remove('測試')
    os.rename('測試.bak', '測試')
    
    # 原檔案內容
    **wen件操作改的流程:**
    1,以讀的模式開啟原wen件。
    2,以寫的模式建立一個新wen件。
    3,將原wen件的內容讀出來修改成新內容,寫入新wen件。
    4,將原wen件刪除。
    5,將新wen件重新命名成原wen件。
    
    # 修改後的內容
    **檔案操作改的流程:**
    1,以讀的模式開啟原檔案。
    2,以寫的模式建立一個新檔案。
    3,將原檔案的內容讀出來修改成新內容,寫入新檔案。
    4,將原檔案刪除。
    5,將新檔案重新命名成原檔案。