『無為則無心』Python基礎 — 42、Python中檔案的讀寫操作(二)

繁華似錦Fighting發表於2022-01-28

(5)檔案物件方法(重點)

1)寫方法

@1.語法

物件物件.write('內容')

@2.示例

# 1. 開啟檔案
f = open('test.txt', 'w')

# 2.檔案寫入
f.write('hello world')

# 3. 關閉檔案
# 只要控制檯顯示Process finished with exit code 0
# 證明程式已經結束,程式碼執行完成。
f.close()

注意:

  1. w a模式:
    如果檔案不存在則建立該檔案;
    如果檔案存在,w模式先清空再寫入,a模式直接末尾追加。
  2. r模式:如果檔案不存在則報錯。

@3.練習說明

"""
測試目標
1. 訪問模式對檔案的影響
2. 訪問模式對write()的影響
3. 訪問模式是否可以省略
"""

# 訪問模式引數可以省略, 如果省略表示訪問模式為r(只讀)

"""
1.r-只讀模式開啟檔案: 
1.1如果檔案不存在,報錯。
1.2不支援寫入操作,表示只讀。
"""
# 如果檔案不存在,報錯
# 結果:FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'
f = open('test.txt', 'w')

# 檔案存在,但不支援寫入操作,表示只讀。
f = open('test.txt', 'r')
# io.UnsupportedOperation: not writable
f.write('aa')
f.close()


"""
2.w-寫入模式開啟檔案:
2.1如果檔案不存在,新建檔案
2.2執行寫入,會覆蓋原有內容
"""
# 檔案存在則直接開啟檔案,檔案不存在則建立該檔案
f = open('1.txt', 'w')
# 寫入內容直接覆蓋原檔案內容。
f.write('bbb')
f.close()


"""
3.a-新增模式開啟檔案:
3.1如果檔案不存在,新建檔案
3.2在檔案原有內容基礎上,追加新內容
"""
# 檔案存在則直接開啟檔案,檔案不存在則建立該檔案
f = open('2.txt', 'a')
# 在檔案原有內容基礎上,追加新內容
f.write('xyz')
f.close()


"""
4.執行一次程式,write()方法會可以分多次向檔案中寫入內容
一次執行中,重複的呼叫write()向檔案中寫入內容,
不會進行覆蓋。
單獨呼叫兩次,第二次的內容會覆蓋第一次的內容。

`with...as...`寫法看 <6、關閉>中有講解
"""
file_name = 'demo.txt'

with open(file_name, 'w', encoding='utf-8') as file_obj:
    file_obj.write('aaa\n')
    file_obj.write('bbb\n')
    file_obj.write('ccc\n')
"""
檔案內容:
aaa
bbb
ccc
"""


"""
5.write('內容')方法中的內容,只能是字串,
如果向輸入一個數值型,需要進行型別轉換,否則會報錯:
TypeError: write() argument must be str, not int
"""
# 程式碼片段如下:
file_obj.write(str(123))

"""
6.write()方法有返回值,
會返回寫入的字元的個數
"""
# 程式碼片段如下:
r = file_obj.write('今天天氣真不錯')
print(r)  # 7

2)讀方法

@1.read()方法

read()方法,用來讀取檔案中的內容,它會將內容全部儲存為一個字串返回。

檔案物件.read(num)

num表示要從檔案中讀取的資料的長度(單位是位元組),如果沒有傳入num,那麼就表示讀取檔案中所有的資料。

示例:

"""
檔案內容如果有換行,底層是\n換行,會佔用1個位元組,
導致read()方法填寫的引數與讀取出來的資料不匹配.
"""
f = open('test.txt', 'r')

# read不寫參數列示讀取所有;
# print(f.read())
print(f.read(10))

f.close()

@2.readlines()方法

readlines()方法可以按照行的方式把整個檔案中的內容進行一次性讀取,並且返回的是一個列表,其中每一行的資料(包括換行符)為一個元素。

f = open('test.txt')
content = f.readlines()

# ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc']
print(content)

# 關閉檔案
f.close()

@3.readline()方法

readline()方法一次讀取一行內容。

f = open('test.txt')  # 只讀方式開啟

# 第一次呼叫`readline( )`方法方法,即讀取檔案第一行內容
content = f.readline()
print(f'第一行:{content}')

# 第二次呼叫`readline( )`方法方法,即讀取檔案第二行內容
# 以此類推
content = f.readline()
print(f'第二行:{content}')

# 關閉檔案
f.close()

"""
輸出結果:
第一行:abcde

第二行:12345
"""

@4.for迴圈方式讀取檔案內容

# 定義檔名
file_name = 'demo.txt'

# 迴圈讀取檔案內容,變數t就檔案內的一行內容
# 遍歷一次,讀取一行。
with open(file_name, encoding='utf-8') as file_obj:
    for t in file_obj:
        print(t)

@5.注意:

我們上邊的練習都是以只讀的方法開啟檔案,然後在讀取資料。以只讀的方式開啟檔案,游標預設是在檔案的開頭,所致使用read()等方法我們能看到讀取的結果。

但是寫入的方式開啟檔案如wa

  • w:開啟檔案後,游標是在檔案的開頭,但是以w方式開啟檔案會自動清空檔案資料,所以我們在呼叫讀取方法,我們依然看不到任何資料。
  • a:開啟檔案後,游標是在檔案內容的末尾的,所以我們在呼叫讀取方法,我們也依然會看不到任何資料。

3)seek()方法

開啟檔案後,檔案指標的位置會影響讀取檔案的資料。

seek()方法的作用:用來移動檔案指標。

語法如下:

檔案物件.seek(偏移量, 起始位置)

起始位置:

  • 0:檔案開頭
  • 1:當前位置
  • 2:檔案結尾

示例:

"""
語法: 檔案物件.seek(偏移量, 起始位置)
0開頭 1當前 2結尾
偏移量:要切換到的位置
"""
# 示例1:r開啟檔案
# 改變讀取資料開始位置
f = open('test.txt', 'r+')

# 1.改變讀取資料開始位置,開頭偏移兩位
f.seek(2, 0)

# 2.檔案指標放到內容結尾
# f.seek(0, 2)

# 讀取檔案
con = f.read()
print(con)
# 關閉檔案
f.close()
"""
輸出結果
cde
12345
abcde
abcde
"""

# 示例2:a開啟檔案
f = open('test.txt', 'a+')

# 檔案指標放到檔案開頭
# 當引數為兩個0的時候,可以簡寫成一個0
# 表示不偏移,起始位置是開頭。
# f.seek(0, 0)
# f.seek(0)

# 讀取檔案
con = f.read()
print(con)
# 關閉檔案
f.close()
"""
輸出結果:
abcde
12345
abcde
abcde
"""

# 示例3.可以只寫偏移量,
# 起始位置預設是0,開頭
file_obj.seek(55)

# 從開頭向後偏移80位
# file_obj.seek(80,0)
# 從當前位置向後偏移70位
# file_obj.seek(70,1)

# io.UnsupportedOperation: can't do nonzero end-relative seeks
# file_obj.seek(-10,2)

4)tell()方法

# tell() 方法用來檢視當前讀取的位置(游標的位置)

示例

with open('demo2.txt','rt' , encoding='utf-8') as file_obj:
    # print(file_obj.read(100))
    # print(file_obj.read(30))

    # seek() 可以修改當前讀取的位置
    # 中文一個字元代表三個位元組,擷取兩個位元組列印就會報錯
    file_obj.seek(9)
    # seek()需要兩個引數
    #   第一個 是要切換到的位置
    #   第二個 計算位置方式
    #       可選值:
    #           0 從頭計算,預設值
    #           1 從當前位置計算
    #           2 從最後位置開始計算

    print(file_obj.read())

    # tell() 方法用來檢視當前讀取的位置
    print('當前讀取到了 -->',file_obj.tell())

(6)關閉

檔案物件.close()

而我們在工作中對檔案的標準處理格式為使用with...as...

# with ... as 語句用法
"""
#with open(file_name) as file_obj 和 file_obj = open(file_name) 是一樣的
#open(file_name)的返回值賦值給了file_obj
with open(file_name) as file_obj :
    # 在with語句中可以直接使用file_obj來做檔案操作
    # 此時這個檔案只能在with中使用,一旦with結束則檔案會自動close()
    print(file_obj.read())
"""

標準寫法

# 確定檔名
file_name = 'hello'

try:
    # 開啟檔案
    with open(file_name) as file_obj :
        # 對檔案進行處理
        print(file_obj.read())
except FileNotFoundError:
    # 檔案不存在進行異常處理
    print(f'{file_name} 檔案不存在~~')

(7)綜合練習:讀取大檔案

需求:讀取大檔案

# 確定檔名
file_name = 'demo.txt'

try:
    # 呼叫open()方法來開啟一個檔案,可以將檔案分成兩種型別
    # 一種,是純文字檔案(使用utf-8等編碼編寫的文字檔案)
    # 一種,是二進位制檔案(圖片、mp3、ppt等這些檔案)
    # open()方法開啟檔案時,預設是以文字檔案的形式開啟的,
    # 但是open()方法預設的編碼為None,
    # 所以處理文字檔案時,必須要指定檔案的編碼。
    with open(file_name,encoding='utf-8') as file_obj:
        # 通過 read() 來讀取檔案中的內容
        # 如果直接呼叫read()它會將文字檔案的所有內容全部都讀取出來,
        # 如果要讀取的檔案較大的話,會一次性將檔案的內容載入到記憶體中,
        # 容易導致記憶體洩漏(溢位)。
        # 所以對於較大的檔案,不要直接呼叫read()方法讀取檔案。
        #
        # read()可以接收一個size作為引數,
        # 該引數用來指定呼叫一次read()方法讀取的字元的數量。
        # 預設值為-1,它會讀取檔案中的所有字元。
        # 可以為size指定一個值,這樣read()方法會讀取指定數量的字元,
        # 每一次讀取都是從上次讀取到位置開始讀取的,
        # 如果字元的數量小於size,則會讀取剩餘所有的,
        # 如果已經讀取到了檔案的最後了,則會返回''空串,
        # content = file_obj.read(-1)
        content = file_obj.read(6)

        """
        這裡可以換成上邊迴圈的方法,讀取內容,
        也可以換成其他的讀取方法。

        # 定義一個變數,來指定每次讀取的大小
        chunk = 100
        # 建立一個迴圈來讀取檔案內容
        while True:
            # 讀取chunk大小的內容
            content = file_obj.read(chunk)

            # 檢查是否讀取到了內容
            # content 空串為false
            if not content:
                # 內容讀取完畢,退出迴圈
                break

            # 輸出內容
            # print(content,end='')
        """
except FileNotFoundError :
    print(f'{file_name} 這個檔案不存在!')

相關文章