1. 程式人生 > >python--檔案流讀寫

python--檔案流讀寫

在講述fileinput模組之前,首先說一下python內建的檔案API—open()函式以及與其相關的函式。

我這裡主要講講其中四個比較重要和常用的方法,更多的方法,可以參考:菜鳥教程http://www.runoob.com/python/file-methods.html

        

(1)file = open(file_name [, access_mode][, buffering])

引數解析:

1. file_name:

file_name變數是一個需要訪問的檔名稱的字串值,在應用中需要用單引號或者雙引號將檔名包裹起來。

 

2. access_mode:

access_mode決定了開啟檔案的模式:只讀,寫入,追加等。這個引數是非強制的,預設檔案訪問模式為只讀(r)

詳細模式可以參考:菜鳥教程http://www.runoob.com/python/python-files-io.html

 

3. buffering:

這個引數用於設定快取區的大小。如果buffering的值被設為0,就不會有快取。如果buffering的值取1,訪問檔案時會寄存行。如果將buffering的值設為大於1的整數,這個整數就為快取區的快取大小。如果取負值,寄存區的緩衝大小則為系統預設。

 

(2)file.flush()方法

用於重新整理緩衝區,,即將緩衝區中的資料立刻寫入檔案,同時清空緩衝區

flush()方法在爬蟲中也用得挺多,在爬蟲過程由於種種原因,程式中斷,寫入快取的資料沒有寫入磁碟很可惜,所以可以手動新增flush()方法

 

(3)file.close()方法

關閉檔案,並將緩衝區的資料寫入檔案中。

 

檔案的快取機制

在寫入檔案內容的時候,在我們呼叫python的write()函式對檔案進行寫入的時候,python解析器會呼叫作業系統的write方法,但值得注意的是,不是馬上儲存到磁碟中的,是先寫到核心的緩衝區裡面,只有當我們主動呼叫flush()函式或者close()函式的時候,才會將緩衝區的內容寫入磁碟中。另外當寫入的資料量大於或者等於緩衝區的大小的時候,寫緩衝會自動同步到磁碟。

例如:

寫20萬行資料結果

file = open('file1.txt','a+')
for i in range(200000):
    file.write('this line is line%s'%i)
file.write('\r\n')

pycharm報出如下的提示

 

因為我設定的buffering是預設的系統的快取大小,所以當寫到1999856行時,就剛好到系統的快取區大小,因為所需要寫的資料大於快取區的大小,所以這些內容直接就寫入了磁碟,而1998856後面的資料在寫入的時候還是先寫到了快取區中,而這些資料的大小顯然是小於快取區大小的,所以被儲存在快取區中,並沒有寫到磁碟。

 

使用flush()方法後,所有在快取區的資料都會寫入到磁碟中

 

如果我直接在呼叫open()方法的時候像下面這樣設定buffering為1,就無需擔心快取的問題了

 

(4)file.seek(offset [,whence])  檔案指標

當檔案進行寫入或者讀取的時候,檔案指標會根據具體的內容進行移動。

引數解析:

offset:偏移量,代表需要移動偏移的位元組數

whence:可選引數,預設值為 0。作用是給offset引數設定起始值,表示要從哪個位置開始偏移。0代表從檔案開頭開始算起,1代表從當前位置開始算起,2代表從檔案末尾算起。

例如以下案例:

file = open('file.txt','a+',1)
for i in range(200):
    file.write('this line is line%s'%i)
    file.write('\r\n')

for line in file:
    print(line)

file.close()

終端沒有列印任何資料

 

如果將程式碼順序修改一下

file = open('file.txt','a+',1)
for i in range(200):
    file.write('this line is line%s'%i)
    file.write('\r\n')
file.close()

f = open('file.txt','r+')
for line in f:
    print(line)
f.close()

終端打印出資料

那麼怎麼用seek()方法呢?

import os
file = open('file.txt','a+',1)
for i in range(200):
    file.write('this line is line%s'%i)
    file.write('\r\n')
    file.seek(0,os.SEEK_SET)
    for line in file:
        print(line)
file.close()

同樣也能打印出資料

上面,我用了os模組的SEEK_SET

os模組有這些內容:

 os.SEEK_SET:表示檔案的相對起始位置

   os.SEEK_CUR:表示檔案的相對當前位置

 os.SEEK_END:表示檔案的相對結束位置

 

關於fileinput模組

fileinput可以對檔案進行細緻化的處理,比直接的open方法有更多檔案操擴充套件。可以一次性迭代一個或者多個檔案,並對檔案進行修改。

 

主要的函式有:

1. input([files[,inplace[,backup]]]) 幫助迭代多個輸入流中的行

2. filename()  返回當前檔案的名稱

3.nestfile()   關閉當前檔案並移動到下一個檔案

4. close()     關閉序列(多個檔案

5. lineno()    返回(多個檔案累計的)當前行號

6. filelineno()  返回在當前檔案的行好

7. isfirstline()  檢查當前是否是當前檔案中的第一行

8. isstdin()     檢查最後一行是否來自sys.stdin

 

可以理解,fileinput模組重點是對多檔案的讀取和適當時候的修改。而沒有直接的寫操作

 

1. input()方法

這個函式是fileinput模組中最重要的一個函式,引數相對複雜一點。

官方的定義:

fileinput.input([files[, inplace[, backup[, bufsize[, mode[, openhook]]]]]])

input(files=None, inplace=False, backup='', bufsize=0, mode='r', openhook=None)

1)files列表,可以是一個檔案,也可以是多個檔案的列表形式

2)inplace  是否對檔案進行就地修改。預設為False,設定為False跟檔案的open區別不大

3)mode  讀取的格式

官方:FileInput opening mode must be one of 'r', 'rU', 'U' and 'rb'  (b:二進位制位元組模式和U:unicode模式)

4)backup  檔案備份,為原本的檔案做一份備份,不作任何修改,其實就是複製。備份的檔名是原本的檔名+備份檔名。注意備份檔案需要把檔案的格式也寫進去。一般backup需要與引數inplace一起使用才有意義。而在設定了inplace=True,一般同時會設定backup引數來備份原本的檔案內容。

 

 

例子:在每一行文字的前面新增 ‘#行號’字樣

單個檔案案例:

for line in fileinput.input('file.txt',inplace=True,mode='r',backup='file_back.txt'):
    num = fileinput.filelineno()
    print('#%s'%num+' '+line)

如果inplace設定為True,即就地修改,必須要有print函式將讀取的資料重新寫回當前的檔案中,否則檔案的資料最後會變成空。所以使用inplace時候必須很小心。

備份後的檔案目錄

 

多個檔案案例
for line in fileinput.input(files=['file.txt','file1.txt'],inplace=True,mode='r',backup='file_back.txt'):
num = fileinput.filelineno()
print('#%s'%num+' '+line

 

 

通常fileinput模組會結合re模組一起使用,例如在對日誌的分析中會很有用

例如,這裡有一個monoodb的log檔案內容

希望獲取日期為11-13的日誌

import fileinput
import re
for line in fileinput.input('mongolog.txt',mode='r',inplace=True,backup='log_backup.txt'):
    pattern = '2018-11-13'
    if re.search(pattern,line):
      print(line)

獲取結果在原log.txt檔案中,備份檔案中的內容與原檔案相同