您好,登錄后才能下訂單哦!
文件操作
初識文件操作
使用python來讀寫文件是非常簡單的操作,我們使用open()函數來打開某個文件,獲取到文件句柄,然后通過文件句柄就可以進行各種各樣的操作了。根據打開形式的不同能夠執行的操作也會有相應的差異。操作文件的方式一般有如下:
r, w, a, r+, w+, a+, rb, wb, ab, r+b, w+b, a+b
默認使用的是r(只讀)模式
只讀操作(r, rb)
f = open("python", mode="r", encoding="utf-8")
content = f.read()
print(content)
f.close()
python.txt
這是python文件
運行結果:
這是python文件
Process finished with exit code 0
需要注意encoding表示編碼集,根據文件的實際保存編碼進行獲取數據,對于我們來說,使用更多的是utf-8。
rb. 讀取出來的數據是bytes類型,,在rb模式下,不能選擇encoding字符集。
f = open("python", mode="rb")
content = f.read()
print(content)
f.close()
python.txt
這是python文件
運行結果:
b'\xe8\xbf\x99\xe6\x98\xafpython\xe6\x96\x87\xe4\xbb\xb6'
Process finished with exit code 0
rb的作用: 在讀取非文本文件的時候. 比如讀取MP3、圖像、視頻等信息的時候就需要用到rb。因為這種數據是沒辦法直接顯示出來的. 在后面文件上傳下載的時候還會用到。還有,我們看的直播,實際上都是這種數據。
路徑
一般分為絕對路徑和相對路徑:
1. 絕對路徑:從磁盤根目錄開始一直到文件名。
2. 相對路徑:同一個文件夾下的文件,相對于當前這個程序所在的文件夾而言,如果在同一個文件夾中。則相對路徑就是這個文件名,如果在上一層文件夾,則要使用../表示上一層文件,如果在上多層文件夾中,則需要使用多次../。
一般在開發過程中推薦大家使用相對路徑。因為在我們把程序拷貝給別人使用的時候. 直接把整個項目文件拷貝出去就能運行,但是如果使用絕對路徑,那還需要拷貝外部的文件。
獲取文件
read()
將文件中的內容全部讀取出來。弊端:占內存。如果文件過大,容易導致內存崩潰,使用時應該小心謹慎。
f = open("../FileOne/靜夜思.txt", mode="r", encoding="utf-8")
content = f.read()
print(content)
靜夜思.txt
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
運行結果:
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
Process finished with exit code 0
read(n)
讀取n個字符,需要注意的是,如果再次讀取,那么會在當前位置繼續去讀而不是從頭讀,如果使用的是rb模式,則讀取出來的是n個字節。
f = open("../FileOne/靜夜思.txt", mode="r", encoding="utf-8")
content = f.read(4)
contentOne = f.read(5)
print(content)
print(contentOne)
靜夜思.txt
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
運行結果:
床前明月
光
疑是地
Process finished with exit code 0
值得注意的是,在這里換行符表示一個字節。前面4個字節,后面接著輸出5個字節。
f = open("../FileOne/靜夜思.txt", mode="rb")
content = f.read(4)
contentOne = f.read(5)
print(content)
print(contentOne)
靜夜思.txt
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
運行結果:
b'\xe5\xba\x8a\xe5'
b'\x89\x8d\xe6\x98\x8e'
Process finished with exit code 0
readline()
一次讀取一行數據,注意:readline()結尾,注意每次讀取出來的數據都會有一個\n 。所以呢,需要我們使用strip()方法來去掉\n或者空格,當然,我們也可以在print后面加上end=""去掉空格。
f = open("../FileOne/靜夜思.txt", mode="r", encoding="utf-8")
contentOne = f.readline()
contentTwo = f.readline()
contentThree = f.readline()
contentFour = f.readline()
print(contentOne.strip())
print(contentTwo.strip())
print(contentThree, end="")
print(contentFour, end="")
靜夜思.txt
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
運行結果:
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
Process finished with exit code 0
readlines()
將每一行形成一個元素,放到一個列表中,將所有的內容都讀取出來,所以也是,容易出現內存崩潰的問題,一般不推薦不推薦使用。
f = open("../FileOne/靜夜思.txt", mode="r", encoding="utf-8")
lst = f.readlines()
print(lst)
for line in lst:
print(line.strip())
靜夜思.txt
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
['床前明月光\n', '疑是地上霜\n', '舉頭望明月\n', '低頭思故鄉']
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
Process finished with exit code 0
從列表里面我們可以看出,每次獲取的行后面都會有換行符/n。因此,打印過程中我們應該使用strip()或者end = ()去掉換行。
循環讀取
f = open("../FileOne/靜夜思.txt", mode="r", encoding="utf-8")
for line in f:
print(line.strip())
靜夜思.txt
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
運行結果:
床前明月光
疑是地上霜
舉頭望明月
低頭思故鄉
Process finished with exit code 0
這種方式是事先就組好了,每次讀取一行的內容,不會產生內存溢出的問題。
注意:
在每次讀取完文件時,應該關閉文件句柄。f.closed()
在執行操作過后可使用刷新機制對文件進行刷新。f.flush()
寫模式(r,rw)
寫的時候注意,如果沒有文件,則會創建文件,如果文件存在,則將原件中原來的內容刪除,再寫入新內容。
f = open("?娃娃", mode="w", encoding="utf-8")
f.write("??獅王")
# f.read() # 嘗試讀取文件,此時只是寫,拋出io.UnsupportedOperation: not readable
f.flush() # 刷新. 養成好習慣
f.close()
創建了文件:小娃娃
??獅王
運行結果:
Process finished with exit code 0
本次文件寫操作執行完畢后,程序結束,控制臺沒有輸出值,只是在列表中創建了文件。
f = open("?娃娃", mode="wb")
f.write("??獅王".encode("utf-8"))
f.flush()
f.close()
創建文件:小娃娃
??獅王
運行結果:
Process finished with exit code 0
wb模式下,可以不指定文件的編碼,但是在寫文件的時候必須將字符串轉換為utf-8的bytes數據,如果不轉化,將會出現一下的錯誤。
TypeError: a bytes-like object is required, not 'str'
追加(a,ab)
在追加模式下. 我們寫入的內容會追加在文件的結尾.
f = open("?娃娃", mode="a", encoding="utf-8")
f.write("麻花藤的最愛")
f.write("是小學生")
f.flush()
f.close()
創建文件:小娃娃
麻花藤的最愛是小學生
運行結果:
Process finished with exit code 0
f = open("?娃娃", mode="ab")
f.write("麻花藤的最愛".encode())
f.write("是小學生".encode())
f.flush()
f.close()
創建文件:小娃娃
麻花藤的最愛是小學生
運行結果:
Process finished with exit code 0
由于編譯器默認的是utf-8,所以在小娃娃文件中顯示的是未改變的字符。
讀寫模式(r+,r+b)
對于讀寫模式,必須是先讀。因為默認光標是在開頭的,準備讀取的,當讀完了之后再進行寫入,我們以后使用頻率最高的模式就是r+。
f = open("?娃娃", mode="r+", encoding="utf-8")
content = f.read()
f.write("麻花藤的最愛")
print(content)
f.flush()
f.close()
運行前的文件:小娃娃
麻花藤的最愛
運行后的文件:小娃娃
麻花藤的最愛麻花藤的最愛
運行結果:
麻花藤的最愛
Process finished with exit code 0
在正常的讀取后,文件的寫入在結尾。
下面演示錯誤操作:
f = open("?娃娃", mode="r+", encoding="utf-8")
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()
運行前的文件:小娃娃
麻花藤的最愛
運行后的文件:小娃娃
哈哈藤的最愛
運行結果:
藤的最愛
Process finished with exit code 0
在沒有任何操作之前,默認的光標在開頭,當寫入“哈哈”以后,“麻花”二字被覆蓋,且光標往后移動了兩個位置,默認讀取從光標后開始讀取。
總結,在r+模式下,必須是先讀取,再寫入。
寫讀(w+,w+b)
先將所有的內容清空,然后寫入,最后讀取,但是讀取的內容是空的,一般不常用。
f = open("?娃娃", mode="w+", encoding="utf-8")
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()
運行前的文件:小娃娃
麻花藤的最愛
運行后的文件:小娃娃
哈哈
運行結果:
Process finished with exit code 0
那么可能有同學會問,先讀不就好了么?
錯。理由:w+ 模式下, 一開始讀取不到數據,然后寫的時候再將原來的內容清空,所以這種操作方式很少用。
追加讀(a+)
a+模式下,不論先讀還是后讀,都是讀取不到數據的。
f = open("?娃娃", mode="a+", encoding="utf-8")
f.write("麻花藤")
content = f.read()
print(content)
f.flush()
f.close()
運行前的文件:小娃娃
愛笑的眼睛
運行后的文件
愛笑的眼睛麻花藤
運行結果:
Process finished with exit code 0
還有一些其它帶b的操作,就不多贅述了,就是把字符換成字節,僅此而已。
其它相關操作
seek(n)
光標移動到n位置,注意,移動的單位是byte,所以如果是utf-8的中文部分要是3的倍數。
通常我們使用seek都是移動到開頭或者結尾。
移動到開頭:seek(0) 。鄭州人流價格 http://www.zzzykdfk.com/
移動到結尾: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()
運行前的文件:小娃娃
123456789
運行后的文件:小娃娃
張國榮
運行結果:
123456789
Process finished with exit code 0
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()
運行前的文件:小娃娃
123456789
運行后的文件:小娃娃
123456789
9
Process finished with exit code 0
truncate()
截斷文件光標后的內容,日常操作過程中幾乎不用。
f = open("小娃娃", mode="w", encoding="utf-8")
f.write("哈哈") # 寫?兩個字符
f.seek(3) # 光標移動到3, 也就是兩個字中間
f.truncate() # 刪掉光標后?的所有內容
f.close()
運行前的文件:小娃娃
麻花藤最愛的人
運行后的文件
哈
運行結果:
Process finished with exit code 0
深坑請注意:在r+模式下,如果讀取了內容,不論讀取內容多少,光標顯示的是多少,再寫入或者操作文件的時候都是在結尾進行的操作。
所以如果想做截斷操作,記住了,要先挪動光標,挪動到你想要截斷的位置,然后再進行截斷關于truncate(n), 如果給出了n. 則從開頭開頭進行截斷,如果不給n,則從當前位置截斷,后面的內容將會被刪除。
修改文件以及另一種打開文件的方式
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", "?娃娃") # 重命名新?件
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。