Python基礎13-文件處理

目錄

用內置函數open打開文件

以文本方式打開文件

只讀模式r

只寫模式w

追加模式a

覆蓋模式+

以二進制方式打開文件

以二進制方式讀

以二進制方式寫

open函數的newline參數

file object的方法

tell顯示當前光標的位置

seek控制光標的移動

truncate切片文件


用內置函數open打開文件

open打開文件,返回文件句柄。通過句柄關閉文件。Python默認使用utf-8編碼,但是open函數不是,open函數會檢測當前操作系統的編碼。read讀取文件的全部內容。

# file1
# 苟利國家生死以
# 豈因禍福避趨之
f = open('file1.txt', encoding='utf-8')
data = f.read()
print(data)
f.close()

以文本方式打開文件

只讀模式r

打開文件有不同的模式。用readable和writable方法判斷是否可讀寫。

只讀模式r,如果進行寫操作會報錯。只讀是默認模式。用read讀取全部內容。用readline讀取一行。用readlines讀取所有行放在一個列表裏。

# file2
# 生不逢時
# 愛不逢人
# 所到之處
# 皆是命數
f = open('file2.txt')
print('line1:--->', f.readline(), end='')
print('line2:--->', f.readline(), end='')
f.close()

f = open('file2.txt')
ss = f.readlines()
print(type(ss), ss)
# <class 'list'> ['生不逢時\n', '愛不逢人\n', '所到之處\n', '皆是命數\n']
for s in ss:
    print(s, end='')
    pass
f.close()

只寫模式w

只寫模式w,如果進行讀操作會報錯。如果文件不存在,那麼會創建一個新文件。如果文件已經存在,那麼會在打開文件時清空文件內容,再進行後續操作,慎重慎重。write方法只寫但不加空格,writelines方法入參一個字符串列表,每個元素寫一下,自己加換行。注意只能寫字符串!

f = open('file3.txt', 'w', encoding='utf-8')
f.write('我是身經百戰了!')
f.write('見的多了!\n')
f.write('西方哪一個國家我沒有去過啊?\n')
f.close()
# file3內容是兩行,寫write需要自己加換行
# 我是身經百戰了!見的多了!
# 西方哪一個國家我沒有去過啊?

f = open('file3.txt', 'w', encoding='utf-8')
seq = ['我是身經百戰了!\n', '見的多了!\n', '西方哪一個國家我沒有去過啊?\n']
f.writelines(seq)
f.close()
# 我是身經百戰了!
# 見的多了!
# 西方哪一個國家我沒有去過啊?

追加模式a

追加模式a,寫的內容寫到文件最後,不清空文件原有內容。適用於寫日誌。

f = open('file4.txt', 'a', encoding='utf-8')
f.write('寫到文件字後\n')
f.close()

覆蓋模式+

可讀可寫,寫就直接從頭開始覆蓋已有內容。

f = open('file4.txt', mode='r+', encoding='gbk')
print(f.readable(), f.writable())
# True True
f.close()

以二進制方式打開文件

應用中,以二進制方式打開文件的情況可能更多,圖片、視頻、音頻等都是以二進制方式讀寫的。

以二進制方式讀

以文本方式打開文件是默認方式,還可以以二進制方式打開,也就是mode='b'。因爲是以二進制方式打開,不再涉及編碼,不能用 encoding入參指定編碼方式。此時,read讀取的數據都是一個一個的字節。如果要將一個一個的字節轉換成可讀的文字,那麼需要進行解碼decode。

# file3
# 我是身經百戰了!
# 見的多了!
# 西方哪一個國家我沒有去過啊?
f = open('file3.txt', mode='rb')
data = f.read()
print(data)
# b'\xe6\x88\x91\xe6\x98\xaf\xe8\xba\xab\xe7\xbb\x8f\xe7\x99\xbe\xe6\x88\x98\xe4\xba\x86\xef\xbc\x81\r\n\xe8\xa7\x81\xe7\x9a\x84\xe5\xa4\x9a\xe4\xba\x86\xef\xbc\x81\r\n\xe8\xa5\xbf\xe6\x96\xb9\xe5\x93\xaa\xe4\xb8\x80\xe4\xb8\xaa\xe5\x9b\xbd\xe5\xae\xb6\xe6\x88\x91\xe6\xb2\xa1\xe6\x9c\x89\xe5\x8e\xbb\xe8\xbf\x87\xe5\x95\x8a\xef\xbc\x9f\r\n'
print(data.decode('utf-8'))
# 解碼爲可讀的字符
f.close()

以二進制方式寫

以二進制方式寫,mode='wb'或'ab'。因爲是以二進制方式打開,不再涉及編碼,不能用 encoding入參指定編碼方式。此時write寫入的都是一個一個字節,,不能直接寫字符串,而要將字符串編碼轉換成字節流。

f = open('file6.txt', mode='wb')
# 以二進制方式寫,不能直接寫字符串,而要將字符串編碼轉換成字節流
f.write('苟利國家生死以,豈因禍福避趨之。'.encode('utf-8'))
f.close()

open函數的newline參數

在大多數操作系統裏面,換行是\n。然而,windows裏面換行是\r\n。

以文本模式打開文件時,newline參數對換行符進行轉換。如果不指定,那麼換行符都是\n。如果傳入newline='',那麼換行符按照操作系統轉換爲特定符號,windows下換行符轉換爲\r\n。

f = open('file1.txt', mode='r', encoding='utf-8')
d = f.readlines()
print(d)
# ['苟利國家生死以\n', '豈因禍福避趨之\n']
f.close()

f = open('file1.txt', mode='r', encoding='utf-8', newline='')
d = f.readlines()
print(d)
# ['苟利國家生死以\r\n', '豈因禍福避趨之\r\n']
f.close()

file object的方法

tell顯示當前光標的位置

文件以utf-8編碼的文本形式打開,剛打開光標在0。讀取一行,共7個漢字,因爲utf-8編碼漢字用3個字節,windows換行\r\n佔兩個字節,所以移動了3*7+2=23個字節。

# file1.txt
# 苟利國家生死以
# 豈因禍福避趨之
f = open('file1.txt', mode='r', encoding='utf-8')
print(f.tell())
# 0
d = f.readline()
print(d, end='')
# 苟利國家生死以
print(f.tell())
# 23
f.close()

seek控制光標的移動

除了read方法,其他光標的移動都是以字節爲單位,seek也是一樣。read讀取3個字符“苟利國”,seek將光標移動到3個字節,也就是utf-8一個字符的位置,再讀取3個字符“利國家”。

如果,用seek方法的第二個參數來控制seek的方式,那麼必須以二進制方式打開文件,此時read讀取的數列也是字節數。

seek第二個參數0,表示從文件開頭開始seek,必須seek正數字節。

seek第二個參數1,表示從當前位置開始seek,可以seek正數、負數。

seek第二個參數2,表示從文件結尾開始seek,必須seek負數字節。

# file1.txt
# 苟利國家生死以
# 豈因禍福避趨之
f = open('file1.txt', mode='rb')
# 剛打開,光標位置爲0,讀取9個字節,得到 苟利國
d = f.read(9)
print(d.decode('utf-8'))
# 苟利國

# seek從頭開始3個字節,再讀取9個字節,得到 利國家
f.seek(3)
d = f.read(9)
print(d.decode('utf-8'))
# 利國家

# whence=1,也就是從當前位置11個字節,跳過生死以和\r\n
# 讀取9個字節,得到 豈因禍
f.seek(11, 1)
d = f.read(9)
print(d.decode('utf-8'))
# 豈因禍

# whence=2,也就是從文件最後倒着讀取,跳過最後的\r\n和避趨之
# 讀取9個字節,得到 避趨之
f.seek(-11, 2)
d = f.read(9)
print(d.decode('utf-8'))
# 避趨之
f.close()

seek方法的一個應用就是讀取文件的最後一行。方法是從文件結尾,倒着seek再讀取。如果不是讀取多行,那麼增大倒着seek的範圍,直到能讀取多行。打印最後一行。

# 如何讀取文件的最後一行
# 方法是嘗試讀取多行,如果不是多行,那麼增加讀取範圍
# 增加範圍不一定用+1的辦法,*2擴大一倍的辦法更快
# file2.txt 用gbk編碼
# 生不逢時
# 愛不逢人
# 所到之處
# 皆是命數
f = open('file2.txt', mode='rb')
offs = -1
while True:
    f.seek(offs, 2)
    d = f.readlines()
    if len(d) > 1:
        print('最後一行是:%s' % d[-1].decode('gbk'))
        break
        pass
    offs *= 2
f.close()

truncate切片文件

truncate是寫操作,因此open文件的時候必須用'+',但是不能用'w+'。同樣也是以字節爲單位。

# file1.txt
# 苟利國家生死以
# 豈因禍福避趨之
f = open('file1.txt', mode='r+', encoding='utf-8')
f.truncate(12)
f.close()
# file1.txt 只剩下 苟利國家 四個字

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章