萬惡之源 - Python檔案操作
初始檔案操作
使用Python來讀寫檔案是非常簡單的操作,我們使用open()函式來開啟一個檔案,獲取到檔案控制代碼,然後通過檔案控制代碼就可以進行各種各樣的操作了
根據開啟方式的不同能夠執行的操作會有相應的差異.
開啟檔案的方式:
r,w,a
r+,w+,a+
rb,wb,ab
r+b,w+b,a+b
預設使用的是r(只讀模式)
只讀操作(r/rb)
f = open('護士少婦蘿莉',mode='r',encoding='utf-8') content = f.read() print(content) f.close() 結果: 標題很好
上邊的內容open()函式開啟護士少婦蘿莉的檔案,然後賦值到一個控制代碼中,open函式中的mode是對這個檔案操作是的一種模式
encoding這個是指定檔案中內容的編碼集,接下來的操作就完全通過控制代碼來操作
f = open('護士少婦蘿莉',mode='rb') content = f.read() print(content) f.close() 結果: b'\xe6\xa0\x87\xe9\xa2\x98\xe5\xbe\x88\xe5\xa5\xbd'
rb 讀出來的資料是bytes型別,在rb模式下,不能encoding字符集
rb的作用:在讀取非文字檔案的時候,比如要讀取mp3,影象,視訊等資訊的時候就需要用到rb,因為這種資料是沒辦法直接顯示出來的
在後面我們檔案上傳下載的時候還會用到.
絕對路徑和相對路徑
1.絕對路徑:從磁碟根目錄開始一直到檔名
2.相對路徑:用一個資料夾下的檔案,相對於當前這個程式所在的檔案而言.如果在同一個檔案中,則相對路勁就是這個檔名.如果再上一層資料夾則要使用../
如果相對還是不能理解,來看下這列子:
你朋友要來找你,知道你在那個樓那一層但是不知道那個一個屋,現在你朋友來到這個樓裡相對他知道的這一層然後開始找你在那個房間
這種操作就是相對路勁,例子中是通過這個樓中的這一層開始尋找,也就是相對於這個樓的某一層
我們更推薦大家使用相對路勁,因為我把這個程式的整個檔案發給你的時候,就可以執行,如果使用絕對路徑還需要額外的拷貝外部檔案給你
讀取檔案的方法
read()將檔案中的內容全部讀取出來;弊端 如果檔案很大就會非常的佔用記憶體,容易導致記憶體奔潰
f = open('path1/小娃娃.txt',mode='r',encoding='utf-8') msg = f.read() f.close() print(msg) 結果: 高圓圓 劉亦菲 張柏芝 楊紫 王菲
read()讀取的時候指定讀取到什麼位置,我們指定先讀取前三個內容,然後在使用read()進行讀取會繼續向後讀取,而不會從頭開始讀取
f = open('path1/小娃娃.txt',mode='r',encoding='utf-8') msg = f.read(3) msg1 = f.read() f.close() print(msg) print(msg1) 結果: 高圓圓 劉亦菲 張柏芝 楊紫 王菲
上邊現在使用的是r模式這樣讀取的就是文字,如果使用rb模式讀取出來的就是位元組
f = open('path1/小娃娃.txt',mode='rb') msg = f.read(3) msg1 = f.read() f.close() print(msg) print(msg1) 結果: b'\xe9\xab\x98' b'\xe5\x9c\x86\xe5\x9c\x86\r\n\xe5\x88\x98\xe4\xba\xa6\xe8\x8f\xb2\r\n\xe5\xbc\xa0\xe6\x9f\x8f\xe8\x8a\x9d\r\n\xe6\x9d\xa8\xe7\xb4\xab\r\n\xe7\x8e\x8b\xe8\x8f\xb2'
readline()讀取每次只讀取一行,注意點:readline()讀取出來的資料在後面都有一個\n
f = open('path1/小娃娃.txt',mode='r',encoding='utf-8') msg1 = f.readline() msg2 = f.readline() msg3 = f.readline() msg4 = f.readline() f.close() print(msg1) print(msg2) print(msg3) print(msg4) 結果: 高圓圓 劉亦菲 張柏芝 楊紫 Process finished with exit code 0
解決這個問題只需要在我們讀取出來的檔案後邊加一個strip()就OK了
f = open('path1/小娃娃.txt',mode='r',encoding='utf-8') msg1 = f.readline().strip() msg2 = f.readline().strip() msg3 = f.readline().strip() msg4 = f.readline().strip() f.close() print(msg1) print(msg2) print(msg3) print(msg4) 結果: 高圓圓 劉亦菲 張柏芝 楊紫
如果有個較大的檔案我們進行讀取不推薦使用以下方法:
f = open('../path1/弟子規',mode='r',encoding='utf-8') print(f.read()) #這樣就是將檔案一次性全部讀取到記憶體中,記憶體容易奔潰
推薦使用的是這種方法:
f = open('../path1/弟子規',mode='r',encoding='utf-8') for line in f: print(line)#這種方式就是在一行一行的進行讀取,它就執行了下邊的功能 print(f.readline()) print(f.readline()) print(f.readline()) print(f.readline())
注意點:讀完的檔案控制代碼一定要關閉
寫模式(w,wb)
在寫檔案的時候我們要養成一個寫完檔案就重新整理的習慣. 重新整理flush()
f = open('../path1/小娃娃.txt',mode='w',encoding='utf-8') f.write('太白很白') f.flush() f.close() 結果: 當我選擇使用w模式的時候,在開啟檔案的時候就就會把檔案中的所有內容都清空,然後在操作
注意點:如果檔案不存在使用w模式會建立檔案,檔案存在w模式是覆蓋寫,在開啟檔案時會把檔案中所有的內容清空.
f1 = open('../path1/小娃娃.txt',mode='r',encoding='utf-8') msg = f1.read() print(msg) # 這個是先檢視小娃娃檔案中有哪些內容 f = open('../path1/小娃娃.txt',mode='w',encoding='utf-8') f.write('太白很白') f.flush() f.close() # 這個是對小娃娃檔案進行覆蓋寫操作 f1 = open('../path1/小娃娃.txt',mode='r',encoding='utf-8') msg = f1.read() print(msg) # 檢視覆蓋寫後的內容
嘗試讀一讀
f1 = open('../path1/小娃娃.txt',mode='w',encoding='utf-8') msg = f1.read() print(msg) 結果: Traceback (most recent call last): File "D:/python_object/path2/test.py", line 563, in <module> msg = f1.read() io.UnsupportedOperation: not readable#模式是w,不可以執行讀操作
wb模式下,不可以指定開啟檔案的編輯,但是寫檔案的時候必須將字串轉換成utf-8的bytes資料
f = open('../path1/小娃娃.txt',mode='wb') msg = '你好'.encode('utf-8') f.write(msg) f.flush()# 重新整理 f.close()
追加(a,ab)
只要是a或者ab,a+都是在檔案的末尾寫入,不論游標在任何位置.
在追加模式下,我們寫入的內容後追加在檔案的末尾
f1 = open('../path1/小娃娃.txt',mode='a',encoding='utf-8') msg = f1.write('這支菸滅了以後')
上圖是沒有追加的圖片
上圖是追加後的圖片
ab這個模式,自己試一下就好了
讀寫模式(r+,r+b)
對於讀寫模式,必須是先讀後寫,因為游標預設在開頭位置,當讀完了以後再進行寫入.我們以後使用頻率最高的模式就是r+
看下正確的操作:
f1 = open('../path1/小娃娃.txt',mode='r+',encoding='utf-8') msg = f1.read() f1.write('這支菸滅了以後') f1.flush() f1.close() print(msg) 結果: 正常的讀取之後,寫在結尾
看下錯誤的操作:
f1 = open('../path1/小娃娃.txt',mode='r+',encoding='utf-8') f1.write('小鬼') msg = f1.read() f1.flush() f1.close() print(msg) 結果: 這樣寫會把小鬼寫在開頭,並且讀出來的是小鬼之後的內容
r+模式一定要記住是先讀後寫
深坑請注意: 在r+模式下. 如果讀取了內容. 不論讀取內容多少. 游標顯示的是多少. 再寫入
或者操作檔案的時候都是在結尾進行的操作.
寫讀模式(w+,w+b)
先將所有的內容清空,然後寫入.最後讀取.但是讀取的內容是空的,不常用
f1 = open('../path1/小娃娃.txt',mode='w+',encoding='utf-8') f1.write('小鬼') msg = f1.read() f1.flush() f1.close() print(msg)
有人說,先讀在寫不就行了.w+模式下 其實和w模式一樣,把檔案清空了,在寫的內容.所以很少人用
追加讀(a+,a+b)
a+模式下,不論是先讀還是後讀,都是讀不到資料的
f = open('../path1/小娃娃.txt',mode='a+',encoding='utf-8') f.write('阿刁') f.flush() msg = f.read() f.close() print(msg)
還有幾個帶b的模式,其實就是對位元組的一些操作,就不多敘述了.
其他相關操作
seek()
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()
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()
truncate() 截斷檔案
f = open("小娃娃", mode="w", encoding="utf-8") f.write("哈哈") # 寫入兩個字元 f.seek(3) # 游標移動到3, 也就是兩個字中間 f.truncate() # 刪掉游標後面的所有內容 f.close() f = open("小娃娃", mode="r+", encoding="utf-8") content = f.read(3) # 讀取9個字元 f.seek(4) print(f.tell()) f.truncate() # 後面的所有內容全部都刪掉 # print(content) f.flush() f.close()
所以如果想做截斷操作. 記住了. 要先挪動游標. 挪動到你想要截斷的位置. 然後再進行截斷
關於truncate(n), 如果給出了n. 則從開頭進行截斷, 如果不給n, 則從當前位置截斷. 後⾯面
的內容將會被刪除
修改檔案以及另一種開啟檔案的方式
檔案修改: 只能將檔案中的內容讀取到記憶體中, 將資訊修改完畢, 然後將原始檔刪除, 將新檔案的名字改成老檔案的名字.
import os with open("../path1/小娃娃", mode="r", encoding="utf-8") as f1,\ open("../path1/小娃娃_new", mode="w", encoding="UTF-8") as f2: content = f1.read() new_content = content.replace("冰糖葫蘆", "⼤白梨") f2.write(new_content) os.remove("../path1/小娃娃") # 刪除原始檔 os.rename("../path1/小娃娃_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", "⼩小娃娃") # 重新命名新⽂檔案