python操做文件

1 python操做文件介紹

  文件是操做系統提供給應用程序操做硬盤的一個對象,一個虛擬單位,用於應用程序將數據永久保存在硬盤中.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.1 f=open()過程分析及mode參數說明

  過程:編輯器

  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 ,肯定是否換行 

1.2 file對象對應的方法說明

  重要的方法: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

1.3 小結

  每打開一個文件,操做系統都要分配一個文件描述符(文件描述符有限),並維護此文件的打開狀態,返回一個值給應用程序.

  關於對文件操做的方法,如open(),f.read(),f.close(),都涉及到系統調用,由於應用程序沒法直接對硬件進行操做.任何對於硬件的操做,都須要經過操做系統來發起系統調用systemcall,來轉換爲底層的硬件操做.

  使用open()函數的經常使用形式是接收2個參數:文件名(file)和模式(mode),使用open()打開一個文件,包含了2個方面的資源:操做系統打開的文件+應用程序的變量,因此在操做完一個文件,必須把這2個方面的資源一塊兒回收.由於python有自動垃圾回收機制,因此,應用程序的資源能夠忽略,但操做系統的資源補必須手動回收,即f.close().

  經常使用 with 關鍵字,來管理上下文,避免忘記 f.close.

1.4 利用關鍵字with管理上下文

  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

1.5 b模式下對文件的操做

  操做文本文件,默認以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模式下,讀取圖片格式的每行內容

2. 文件內光標的移動

  原文本文件內容爲:

張三    男    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 

3 python修改文件的2種方式 

  注意:硬盤內的數據的修改都是以新的覆蓋舊的.

  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')   #重命名
相關文章
相關標籤/搜索