1. 初識文件操作 使⽤python來讀寫⽂件是非常簡單的操作。我們使⽤open()函數來打開⼀個⽂件,獲取到⽂ 件句柄,然後通過⽂件句柄就可以進⾏各種各樣的操作了,根據打開⽅式的不同能夠執⾏的操 作也會有相應的差異。 打開⽂件的⽅式: r, w, a, r+, w+, a+, rb, wb, ab ...
1. 初識文件操作
使⽤python來讀寫⽂件是非常簡單的操作。我們使⽤open()函數來打開⼀個⽂件,獲取到⽂ 件句柄,然後通過⽂件句柄就可以進⾏各種各樣的操作了,根據打開⽅式的不同能夠執⾏的操 作也會有相應的差異。 打開⽂件的⽅式: r, w, a, r+, w+, a+, rb, wb, ab, r+b, w+b, a+b 預設使⽤的是r(只讀)模式2. 只讀操作(r,rb)
f = open("護⼠少婦嫩模.txt",mode="r", encoding="utf-8") content = f.read() print(content) f.close()需要註意encoding表⽰編碼集,根據⽂件的實際保存編碼進⾏獲取數據,對於我們⽽⾔,更 多的是utf-8. rb:讀取出來的數據是bytes類型,在rb模式下,不能選擇encoding字元集。
f = open("護⼠少婦嫩模.txt",mode="rb" ) content = f.read() print(content) f.close()rb的作⽤: 在讀取非⽂本⽂件的時候,比如讀取MP3、圖像、視頻等信息的時候就需要⽤到rb。因為這種數據是沒辦法直接顯⽰出來的,在後⾯我們⽂件上傳下載的時候還會⽤到,還有,我們看的直播,實際上都是這種數據。 絕對路徑和相對路徑:
結果: b'\xe6\xaf\x85\xe5\x93\xa5, \xe5\xa4\xaa\xe7\x99\xbd, wuse\n\xe5\x91\xb5\xe5\x91\xb5\n\xe6\x97\xa5\xe5\xa4\xa9'
1. 絕對路徑:從磁碟根⽬錄開始⼀直到⽂件名。 2. 相對路徑:同⼀個⽂件夾下的⽂件,相對於當前這個程式所在的⽂件夾⽽⾔,如果在同 ⼀個⽂件夾中,則相對路徑就是這個⽂件名,如果在上⼀層⽂件夾,則要../。我更推薦⼤家使⽤相對路徑,因為在我們把程式拷⻉給別⼈使⽤的時候,直接把項⽬拷⻉走 就能運⾏,但是如果⽤絕對路徑,那還需要拷⻉外部的⽂件。 讀取⽂件的⽅法:
2.1 read()
read():將⽂件中的內容全部讀取出來。弊端: 占記憶體,如果⽂件過⼤,容易導致記憶體崩潰。f = open("../def/哇擦.txt", mode="r", encoding="utf-8") content = f.read() print(content)
結果: 友誼地久天⻓, 愛⼀點, 可惜我是⽔瓶座 ⼀⽣中最愛
2.2 read(n)
read(n):讀取n個字元,需要註意的是,如果再次讀取,那麼會在當前位置繼續去讀⽽不 是從頭讀,如果使⽤的是rb模式,則讀取出來的是n個位元組。f = open("../def/哇擦.txt", mode="r" encoding="utf-8") content = f.read(3) print(content)
結果: 友誼地
f = open("../def/哇擦.txt", mode="rb") content = f.read(3) print(content)
結果: b'\xe5\x8f\x8b'
f = open("../def/哇擦.txt", mode="r", encoding="utf-8") content = f.read(3) content2 = f.read(3) print(content) print(content2)
結果: 友誼地 久天⻓
2.3 readline()
readline():⼀次讀取⼀⾏數據。註意: readline()結尾,註意每次讀取出來的數據都會有⼀ 個\n,所以呢,需要我們使⽤strip()⽅法來去掉\n或者空格。f = open("../def/哇擦.txt", mode="r", encoding="utf-8") content = f.readline() content2 = f.readline() content3 = f.readline() content4 = f.readline() content5 = f.readline() content6 = f.readline() print(content) print(content2) print(content3) print(content4) print(content5) print(content6)
結果: 友誼地久天⻓, 愛⼀點, 可惜我是⽔瓶座 ⼀⽣中最愛
2.4 readlines()
readlines():將每⼀⾏形成⼀個元素,放到⼀個列表中,將所有的內容都讀取出來,所以 也是,容易出現記憶體崩潰的問題,不推薦使⽤。f = open("../def/哇擦.txt", mode="r", encoding="utf-8") lst = f.readlines() print(lst) for line in lst: print(line.strip())
2.5 迴圈讀取
這種⽅式是組好的,每次讀取⼀⾏內容,不會產⽣記憶體溢出的問題。f = open("../def/哇擦.txt", mode="r", encoding="utf-8") for line in f: print(line.strip())註意: 讀取完的⽂件句柄⼀定要關閉 f.close()
3. 寫模式(w,wb)
寫的時候註意,如果沒有⽂件,則會創建⽂件,如果⽂件存在,則將原件中原來的內容刪除,再 寫入新內容。f = open("⼩娃娃", mode="w", encoding="utf-8") f.write("⾦⽑獅王") f.flush() # 刷新. 養成好習慣 f.close()嘗試讀⼀讀
f = open("⼩娃娃", mode="w", encoding="utf-8") f.write("⾦⽑獅王") f.read() # not readable 模式是w. 不可以執⾏讀操作 f.flush() f.close()wb模式下,可以不指定打開⽂件的編碼,但是在寫⽂件的時候必須將字元串轉化成utf-8的 bytes數據。
f = open("⼩娃娃", mode="wb") f.write("⾦⽑獅王".encode("utf-8")) f.flush() f.close()
4. 追加(a,ab)
在追加模式下,我們寫入的內容會追加在⽂件的結尾。f = open("⼩娃娃", mode="a", encoding="utf-8") f.write("麻花藤的最愛") f.flush() f.close()ab模式⾃⼰試⼀試就好了
5. 讀寫模式(r+,r+b)
對於讀寫模式,必須是先讀,因為預設游標是在開頭的,準備讀取的。當讀完了之後再進⾏ 寫入,我們以後使⽤頻率最⾼的模式就是r+。 正確操作:f = open("⼩娃娃", mode="r+", encoding="utf-8") content = f.read() f.write("麻花藤的最愛") print(content) f.flush() f.close()錯誤操作:
結果: 正常的讀取之後, 寫在結尾
f = open("⼩娃娃", mode="r+", encoding="utf-8") f.write("哈哈") content = f.read() print(content) f.flush() f.close() 結果: 將開頭的內容改寫成了"哈哈", 然後讀取的內容是後⾯的內容.所以記住: r+模式下,必須是先讀取,然後再寫入。
6. 寫讀(w+,w+b)
先將所有的內容清空,然後寫入,最後讀取,但是讀取的內容是空的,不常⽤。f = open("⼩娃娃", mode="w+", encoding="utf-8") f.write("哈哈") content = f.read() print(content) f.flush() f.close()有⼈會說,先讀不就好了麽? 錯。w+ 模式下,⼀開始讀取不到數據,然後寫的時候再將原來的內容清空,所以,很少⽤。
7. 追加讀(a+)
a+模式下,不論先讀還是後讀,都是讀取不到數據的。f = open("⼩娃娃", mode="a+", encoding="utf-8") f.write("⻢化騰") content = f.read() print(content)還有⼀些其他的帶b的操作,就不多贅述了,就是把字元換成位元組,僅此⽽已。
f.flush() f.close()
8. 其他相關操作
8.1 seek(n)
seek(n):游標移動到n位置,註意,移動的單位是byte,所以如果是UTF-8的中⽂部分要 是3的倍數。 通常我們使⽤seek都是移動到開頭或者結尾。 移動到開頭: seek(0) 移動到結尾: seek(0,2) seek的第⼆個參數表⽰的是從哪個位置進⾏偏移,預設是0,表 ⽰開頭,1表⽰當前位置,2表⽰結尾。f = open("⼩娃娃", mode="r+", encoding="utf-8") f.seek(0) # 游標移動到開頭 content = f.read() # 讀取內容, 此時游標移動到結尾 print(content) f.seek(0) # 再次將游標移動到開頭 f.seek(0, 2) # 將游標移動到結尾 content2 = f.read() # 讀取內容. 什麼都沒有 print(content2)
f.seek(0) # 移動到開頭 f.write("張國榮") # 寫⼊信息. 此時游標在9 中⽂3 * 3個 = 9
f.flush() f.close()
8.2 tell()
tell():使⽤tell()可以幫我們獲取到當前游標在什麼位置。f = open("⼩娃娃", mode="r+", encoding="utf-8") f.seek(0) # 游標移動到開頭 content = f.read() # 讀取內容, 此時游標移動到結尾 print(content) f.seek(0) # 再次將游標移動到開頭 f.seek(0, 2) # 將游標移動到結尾 content2 = f.read() # 讀取內容. 什麼都沒有 print(content2)
f.seek(0) # 移動到開頭 f.write("張國榮") # 寫⼊信息. 此時游標在9 中⽂3 * 3個 = 9
print(f.tell()) # 游標位置9
f.flush() f.close()
8.3 truncate() 截斷文件
f = open("⼩娃娃", mode="w", encoding="utf-8") f.write("哈哈") # 寫⼊兩個字元 f.seek(3) # 游標移動到3, 也就是兩個字中間 f.truncate() # 刪掉游標後⾯的所有內容 f.close()深坑請註意: 在r+模式下,如果讀取了內容,不論讀取內容多少,游標顯⽰的是多少,再寫入 或者操作⽂件的時候都是在結尾進⾏的操作。 所以如果想做截斷操作,記住了,要先挪動游標,挪動到你想要截斷的位置,然後再進⾏截斷。 關於truncate(n),如果給出了n,則從開頭開頭進⾏截斷,如果不給n,則從當前位置截斷,後⾯ 的內容將會被刪除。
f = open("⼩娃娃", mode="r+", encoding="utf-8") content = f.read(3) # 讀取12個字元 f.seek(4) print(f.tell()) f.truncate() # 後⾯的所有內容全部都刪掉 # print(content) f.flush() f.close()
9. 修改文件以及另一種打開文件的方式
⽂件修改: 只能將⽂件中的內容讀取到記憶體中,將信息修改完畢,然後將源⽂件刪除,將新 ⽂件的名字改成老⽂件的名字。# ⽂件修改 import os with open("⼩娃娃", mode="r", encoding="utf-8") as f1,\ open("⼩娃娃_new", mode="w", encoding="UTF-8") as f2: content = f1.read() new_content = content.replace("冰糖葫蘆", "⼤⽩梨") f2.write(new_content) os.remove("⼩娃娃") # 刪除源⽂件 os.rename("⼩娃娃_new", "⼩娃娃") # 重命名新⽂件弊端: ⼀次將所有內容進⾏讀取,記憶體溢出。解決⽅案: ⼀⾏⼀⾏的讀取和操作。
import os with open("⼩娃娃", mode="r", encoding="utf-8") as f1,\ open("⼩娃娃_new", mode="w", encoding="UTF-8") as f2: for line in f1: new_line = line.replace("⼤⽩梨", "冰糖葫蘆") f2.write(new_line) os.remove("⼩娃娃") # 刪除源⽂件 os.rename("⼩娃娃_new", "⼩娃娃") # 重命名新⽂件