文件是操做系統提供給應用程序操做硬盤的一個對象,一個虛擬單位,用於應用程序將數據永久保存在硬盤中.python
在python中,操做文件主要有如下幾個步驟:vim
# 1. 打開文件,獲得文件句柄並賦值給一個變量,其完整的格式以下: f=open('file', mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) # 2. 經過句柄對文件進行操做(讀/寫/追加等) data=f.read() # 3. 關閉文件,回收操做系統的資源(關閉後,文件已不可打開,由於操做系統方面的資源已被關閉) f.close() # 4. 刪除文件del f ,此步驟能夠忽略不寫(應用程序級別),由於python解釋器有自動的垃圾回收機制,但刪除步驟del f,必須放在f.close以後.
open()函數中接收的參數解釋(經常使用的是file,mode,encoding):windows
file: 必需,文件路徑(相對或者絕對路徑),注意windows系統下一般須要在前面加 r ,防止轉義 mode: 可選,文件打開模式,默認是rt,即以只讀方式打開文本文件 buffering: 設置緩衝 encoding: 可選,操做文件使用的字符編碼,通常使用utf8,若是不指定,就以操做系統的字符編碼打開文件(編碼不對會亂碼) errors: 報錯級別 newline: 區分換行符 closefd: 傳入的file參數類型 opener:
過程:編輯器
1)由應用程序向操做系統發起系統調用open(...).
2)操做系統打開該文件,並返回一個文件句柄給應用程序.
3)應用程序將文件句柄賦值給變量f.函數
注意:open()打開的是本機上文件,而且,open()函數內不管是讀/寫/追加內容,統一使用 \n 做爲換行符.工具
mode參數說明:編碼
其中,重要的以下:操作系統
# 對於文本文件(默認rt),讀寫都是以字符串爲單位,須要指定字符編碼 r :只讀模式【默認模式,文件必須存在,不存在則拋出異常】 w :只寫模式【不可讀;不存在則建立;存在則清空內容】 a :追加寫模式【不可讀;不存在則建立;存在則只追加內容】,應用場景:日誌文件 # 對於非文本文件(如圖片,視頻等),只能以b模式處理,且無需考慮字符編碼 rb :讀取時,解碼decode='utf-8',能夠看到本來的內容 wb :寫入時,指定encode='utf-8'寫入,就是bytes類型 ab 注意:以b方式打開時,讀取到的內容是字節類型,寫入時也須要提供字節類型,不能指定編碼
實例:日誌
f=open('b.txt',encoding='utf-8') #這樣寫,默認省略了mode='rt',不能只寫t,不寫r,會報錯,能夠只寫r,不寫t f=open('b.txt',encoding='utf-8') #mode='w',文件中內容會被覆蓋,無此文件會新建立 data=f.write('asdasd') #只讀模式下不可寫,not writable f=open('b.txt',mode='w',encoding='utf-8') #mode='w',文件中內容會被覆蓋,無此文件會新建立 f.write('aaaaaaaa\nbbbbbbbb\n') data=f.read() #只寫模式下不可讀,not readable f=open('b.txt',mode='rt',encoding='utf-8') print(f.readline(),end='') #print自帶換行,readline以行爲單位讀取,不加end=''會多一行空行 with open('b.txt',mode='w',encoding='utf-8') as f: f.write('aaaaa\nbbbbb\n') #每寫完一行,光標移到最後 f.write('ccccc\nddddd\n') #只寫模式下須要本身加換行符 \n with open('b.txt',mode='w',encoding='utf-8') as f: f.writelines(['111111\n','222222\n','3333333\n']) #至關於for循環列表內元素後放到文件中,對應readlines() with open('b.txt',mode='w',encoding='utf-8') as f: f.write('111111\n22222\n333333') #此種模式下寫入,只能夠接收字符串,不像writelines()列表,能夠是全部數據類型 # a 模式,追加寫模式,一般用於日誌文件,文件存在時,追加內容,光標移到末尾,文件不存在則建立空文件並追加內容 with open('b.txt',mode='a',encoding='utf-8') as f: f.write('111111\n') #追加寫模式,每次追加寫光標都在末尾,須要手工添加換行符 \n ,肯定是否換行
重要的方法:code
#如下在沒有執行f.close()的狀況下,資源還未關閉,有文件光標的概念 f.read() #剛打開時,光標停在內容開頭,當讀取完全部內容,光標移動到文件末尾 f.readline() #以行爲單位讀取文件內容,讀取完一行內容後,光標會移動到第二行首部(文件過大,讀取可能會卡死) f.readlines() #讀取全部內容,以行分隔每一行內容,並存放於列表中,讀完後,光標移到最後(文件過大,可能會卡死) ------------------------------------ f=open('b.txt',mode='rt',encoding='utf-8') print(f.readlines()) #['aaaaaaaa\n', 'bbbbbbbb\n']以行爲單位切分爲一個列表,對應writelines([list]) ------------------------------------ f.write('1111\n222\n') #針對文本模式的寫,須要本身寫換行符 f.write('1111\n222\n'.encode('utf-8')) #針對b模式的寫,須要本身寫換行符 f.writelines(['333\n','444\n']) #文件模式,對應讀的readlines f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式 ------------------------------------ f.readable() #判斷文件是否可讀,可讀返回True,不然返回False f.writable() #文件是否可寫,可寫返回True,不然返回False f.closed #判斷文件是否關閉,是返回True,不然返回False f.encoding #若是文件打開模式爲b,則沒有該屬性 f.flush() #馬上將文件內容從內存刷到硬盤 f.name
每打開一個文件,操做系統都要分配一個文件描述符(文件描述符有限),並維護此文件的打開狀態,返回一個值給應用程序.
關於對文件操做的方法,如open(),f.read(),f.close(),都涉及到系統調用,由於應用程序沒法直接對硬件進行操做.任何對於硬件的操做,都須要經過操做系統來發起系統調用systemcall,來轉換爲底層的硬件操做.
使用open()函數的經常使用形式是接收2個參數:文件名(file)和模式(mode),使用open()打開一個文件,包含了2個方面的資源:操做系統打開的文件+應用程序的變量,因此在操做完一個文件,必須把這2個方面的資源一塊兒回收.由於python有自動垃圾回收機制,因此,應用程序的資源能夠忽略,但操做系統的資源補必須手動回收,即f.close().
經常使用 with 關鍵字,來管理上下文,避免忘記 f.close.
with關鍵字的做用:管理上下文,即打開文件,完成操做後,自動回收資源,無需close了.
with open('a.txt','r') as f1,open('b.txt','w') as f2: #同時處理多個文件使用逗號隔開,要換行須要使用續行符 \ data=f1.read() #子代碼塊 f2.write(data) #子代碼塊
實例:
with open('b.txt',encoding='utf-8') as f: #此種方式不會形成內存被撐爆,讀一行取一行 for line in f: print(line,end='') ------------------------------- for line in f.readlines(): #此種方式可能會形成系統卡頓(文件過大)甚至崩潰 print(line,end='') #由於是一次性讀 結果-------------------------- aaaaaaaa bbbbbbbb
操做文本文件,默認以rt模式操做,只能對文本文件操做,不能對非文本文件進行操做.
以b模式能夠操做文本文件,讀寫都是以bytes爲單位,能夠進行encode編碼/decode解碼操做.
b模式下操做圖片,視頻等其餘文件,不能進行decode操做.
對全部類型的文件操做,最好使用b模式,b模式具備跨平臺性,但須要對數據作轉換,即encode.
實例:
# b 模式,不能單獨使用,必須是rb/wb/ab # b 模式下讀寫都是以bytes爲單位,無需考慮字符編碼的問題,不能也無需指定encoding參數 with open('1.jpg',mode='rb') as f: data=f.read() #文件不存在會報錯No such file or directory print(data,type(data)) #圖片格式底層也是用bytes字節串/二進制存儲 with open('b.txt',mode='rb') as f: #b模式下,讀取文本文件(文本中存在且有內容) data=f.read() print(data,type(data)) print(data.decode('utf-8')) #解碼decode才能夠看到對應文件中的內容(以什麼編碼就以什麼解碼),顯示在pycharm工具中 with open('c.txt',mode='wb') as f: msg='阿薩德' data=f.write(msg.encode('utf-8')) #b模式下需指定編碼encode寫入內容至文件中,文件中內容爲 阿薩德 with open('c.txt',mode='rb') as f: data=f.read() print(type(data)) #<class 'bytes'>字節串類型 print(data.decode('utf-8')) #讀取的文件內容爲阿薩德,指定編碼讀內容 with open('c.txt',mode='ab') as f: f.write('撒旦'.encode('utf-8')) #指定encode追加寫入 with open('1.jpg',mode='rb') as f: for line in f: print(line) #b模式下,讀取圖片格式的每行內容
原文本文件內容爲:
張三 男 20 11122233344 李四 男 21 22233344455 王一 女 22 33344455566
執行with語句:
with open('c.txt','r+',encoding='utf-8') as f: #使用r+,光標在開頭 f.seek(9) #指定偏移量,光標從開頭日後移動3個位置(注意偏移量單位是字節) print(f.tell()) #查看當前光標位置 print(f.read()) #上面指定了偏移量,這裏讀出來的結果會跳過光標以前的內容 ---------讀出的結果 9 男 20 11122233344 李四 男 21 22233344455 王一 女 22 33344455566
注意:硬盤內的數據的修改都是以新的覆蓋舊的.
1)將硬盤存放的該文件的內容所有加載到內存,在內存中修改,修改完畢後,再把結果由內存覆蓋到硬盤(word,vim,nodpad++等編輯器).缺點:文件若是過大,可能致使機器卡死.
with open('c.txt',mode='r',encoding='utf-8') as f: data=f.read() data=data.replace('張三','張三三') #replace替換內容,注意這裏僅僅是在內存中替換,並無寫到硬盤 with open('c.txt',mode='w',encoding='utf-8') as f: f.write(data) #內存中已有替換的內容被寫入到硬盤
2)建議使用:以讀的方式打開原文件,將硬盤存放的該文件的內容一行一行地讀入內存(for循環),修改完畢就寫入新文件,最後用新文件覆蓋源文件.(解決內存佔用大的問題,但會多打開一個新文件,佔用硬盤資源)
import os with open('c.txt',mode='r',encoding='utf-8') as f_read,\ open('cc.txt',mode='w',encoding='utf-8') as f_write: for line in f_read: if '李四' in line: line=line.replace('李四','李四四') f_write.write(line) #這裏跟判斷無關 os.remove('c.txt') #刪除 os.rename('cc.txt','c.txt') #重命名