文件的讀寫有三種形式:讀、寫和追加。
一、讀模式 r 和讀寫模式 r+
1、讀模式 r
讀模式r特點:(1)只能讀,不能寫;(2)文件不存在時會報錯。
(1)例:讀取當前目錄下的books.txt文件,該文件如下所示。
解析:
a、用open打開文件,在python3中只有open。python2可以用open和file。關閉文件是close()。一般有開就有關
b、如果在當前目錄,可以直接寫文件名,否則需添加路徑。
c、如果不寫 'r',即寫成 f = open('books.txt'),也是默認讀模式。
d、read可以將文件所有的內容都讀出來
e、另外,有時需要添加解碼格式 encoding ,格式為:
f = open('books','r',encoding='utf-8')
(2)
read:讀取文件全部內容
readline:讀取一行
readlines:讀取每一行,並且放到一個list里
2、讀寫模式 r+
讀寫模式r+特點:(1)文件不存在時會報錯;(2)可以讀,也可以寫,是覆蓋寫,會把文件最前面的內容覆蓋
‘水滸傳’把‘平凡的’三個字覆蓋,原來的文件變為:
二、寫模式 w 和寫讀模式 w+
1、寫模式
寫模式w特點:(1)只能寫,不能讀;(2)寫的時候會把原來文件的內容清空;(3)當文件不存在時,會創建新文件。
如下,寫入‘水滸傳’時,將原來的內容都清空。
f.flush():有時我們用f.write()后,會發現沒有寫入文件,這是因為內容存在了緩沖區,需要等緩沖區滿了之后,再把所有數據寫入。此時可以用f.flush()強制把緩沖區里面的數據寫到磁盤上。
2、寫讀模式 w+
寫讀模式w+特點:(1)可以寫,也可以讀;(2)寫的時候會把原來文件的內容清空;(3)當文件不存在時,會創建新文件。
三、追加模式a和追加讀模式a+
1、追加模式a
追加模式a特點:(1)不能讀;(2)可以寫,是追加寫,即在原內容末尾添加新內容;(3)當文件不存在時,創建新文件。
將‘水滸傳’添加到原內容的末尾
2、追加讀a+模式
追加讀a+模式特點:(1)可讀可寫;(2)寫的時候是追加寫,即在原內容末尾添加新內容;(3)當文件不存在時,創建新文件。
以上幾種模式,可以用下表來總結:
讀寫模式 | 是否可讀 | 是否可寫 | 文件不存在時 |
r | 是 | 否 | 報錯 |
r+ | 是 | 是,覆蓋寫 | 報錯 |
w | 否 | 是,清空原內容 | 創建新文件 |
w+ | 是 | 是,清空原內容 | 創建新文件 |
a | 否 | 是,追加寫 | 創建新文件 |
a+ | 是 | 是,追加寫 | 創建新文件 |
四、文件指針
文件指針用來記錄文件走到哪里。
文件指針是很重要的,我們看下面的例子中,read將books.txt的內容全部讀了出來,readline則沒有讀出任何內容。原因是read讀完之后,文件指針到了文件的末尾,此時readline接着從這個位置開始讀,肯定是沒內容的。因此有時需要調整文件指針的位置。
seek可以移動文件指針,移動后只是針對讀,用追加模式寫的時候,還是在末尾寫。
另外,seek(num),這個num指的是字符,不是行。
在上面的代碼中,加一句f.seek(0),即可將指針移到文件開頭。這次,readline就可以從頭開始讀了。
五、自動關閉文件
with可以自動關閉文件,用法如下:
with open('books.txt','a+') as f: f.write('\n三體')
六、文件修改
1、簡單粗暴直接修改
最簡單粗暴的修改文件,步驟是:
(1)打開文件,獲取文件內容;
(2)對內容進行修改;
(3)清空原來文件的內容;
(4)把新的內容寫進去。
這種方法很簡單,下面看一個小例子----文件username里存放了姓名和密碼,如下圖格式。我們要在所有姓名前加上‘A班_’
因為'A班_'中含有中文,需要叫上encoding='utf-8',否則會出現亂碼。
2、備份文件的方法
當文件很大時,剛剛的方法在一次性讀取文件內容和寫入新內容時,耗時長,占用磁盤空間也較大。
備份文件的方法可以建立一個備份文件,修改一行寫一行,具體步驟如下:
(1)打開2個文件,原文件a和備份文件b。如a.txt b.txt.bak
(2)刪除a文件,將b文件名改為a文件名
例:將文件words里的“花”改成“flower”
七、小練習
1、產生手機號 前幾位一樣1861253 后四位隨機,寫到文件里。
分析:(1)首先要隨機產生一些四位數,位數不足的要補0,zfill可以給字符串補0;
(2)需要寫到文件里,可以用w或者a模式。文件有打開就要有關閉。
import random f = open('phones.txt','w') num = int(input('請輸入你要產生的手機號個數:')) for i in range(num): start = '1861253' random_num = str(random.randint(1,9999)) new_num = random_num .zfill(4) #不夠4位就補0,僅對字符串可以使用 phone_num = start + new_num f.write(phone_num+'\n') f.close()
2、監控服務器日志,如果ip出現的次數大於50次,就把該ip加入黑名單。日志文件的格式如下圖
分析:(1)首先,我們應該從日志里提取出所有ip。根據日志文件的格式,我們可以看到每一行的開頭是ip,那么可以一行一行的讀取數據,然后用空格進行分割,則該行第一個元素就是ip。(2)然后需要統計每一個ip出現的次數,最直接想到的就是count。(3)找到出現次數大於50次的ip,打印出來。
import time point = 0#記錄文件指針的位置 while True: f = open(r'D:\access.log',encoding='utf-8') all_ips = [] f.seek(point)#移動文件指針,本次接着上次的位置繼續讀 for line in f: ip = line.split()[0]#每行第一個元素為IP all_ips.append(ip)#存放所有的ip,不去重 point = f.tell()# 獲取文件當前指針位置 ips_set = set(all_ips)#去重 for i in ips_set: if all_ips.count(i)>50: print('應該加入黑名單的ip是:%s\n'%i) time.sleep(60)#暫停60s
運行結果為: