Python文件處理 Python文件處理 在python中,要對一個文件進行操作,得把文件抽象為Streams流或者說file object或者叫file-like objects。 這樣將文件當作一個流對象來處理就方便多了。Stream對象提供了很多操作方法(如read(),write()等), ...
Python文件處理
Python文件處理
在python中,要對一個文件進行操作,得把文件抽象為Streams流或者說file object或者叫file-like objects。
這樣將文件當作一個流對象來處理就方便多了。Stream對象提供了很多操作方法(如read(),write()等),操作這些Stream對象就是操作文件對象。所以python的概念里,文件對象即Stream。主要想說明的是:文件在python中都抽象成了Stream。
Stream是簡介操作I/O,所以要准許各種類型I/O設備各自的操作。操作Stream不是代表I/O的數據全部存在記憶體中,而是通過Stream操作I/O。
note1:python中這三種叫法是一樣的:File object/Stream/File-like objects
note2:除了文件會抽象成為Stream,依據不同的創建Stream的方式,可分為磁碟文件or其它類型存儲中的文件or通信設備(通信設備中如:stdin/stdout,sockets,in-memery buffers,pipes等),這些都可以通過它們自己獨特的方式抽象為Stream,然後都可以通過Stream的介面像操作文件一樣間接操作這些可以讀寫i/o的實體
官方文檔:
The io module provides Python’s main facilities for dealing with various types of I/O. There are three main types of I/O: text I/O, binary I/O and raw I/O. These are generic categories, and various backing stores can be used for each of them. A concrete object belonging to any of these categories is called a file object. Other common terms are stream and file-like object. |
怎麼將文件變為python中的file-object文件對象?
對於磁碟文件這類io實體,python是通過內置函數open()進行創建
file_oject = open(r'測試文件.txt','r') # 通過open得到文件對象 file_contents = file_object.read() # 操作文件對象的方法read,讀取文件中內容。通常我們把這種通過間接的對象去操作實體對象的對象叫handle句柄.就像遙控板和電視機關係。 if file_contents: print(file_contents)文件對象提供哪些操作呢?讀、寫、改?
上面open操作我們看到,除了提供文件路徑,還有第二個參數。這個參數是文件打開的模式。通過指定不同的模式,就限制了文件對象的讀寫行為。下表說明不同模式的意思:
character | meaning |
‘r’ | open for reading(default) |
‘w’ | open for writing,truncating the file first |
‘a’ | open for writing,appending to the end of the file if it exists |
‘x’ | open for exclusive creation,writing,non-reading,failing if the file already exists |
‘b’ | binary mode |
‘t’ | text mode(default) |
‘+’ | open a disk file for updating (reading and writing) |
‘U’ | univeral newlines mode(deprecated棄用;不贊成) |
除去’U’模式,其它模式還可以分為3類,前四個都是打開操作一類,’b’ 和’t’是決定是二進位還是文本一類。有’+‘和沒’+‘ 又是一類是否可讀寫。三類組合下,就有16種組合模式,每種組合模式有自己的特點和其返回的對象所能支持的操作。
從兩個角度來說明什麼限制了文件對象能支持的操作:
- 就是上面提到的打開模式限制。
- 文件對象類型決定了其支持的操作(雖然第一中情況也部分決定了返回的file object對象類型,但是肯定存在其它方式創建file object的)。
Independently of its category, each concrete stream object will also have various capabilities: it can be read-only, write-only, or read-write. It can also allow arbitrary random access (seeking forwards or backwards to any location), or only sequential access (for example in the case of a socket or pipe). |
就是說依據Stream所屬類型,stream也將有各種能力,它可以read-only,write-only,read-write.除了讀寫基本操作能力,我們還需要能夠指哪打哪的能力,那就任意訪問Stream任何地方,即可以支持前後尋找seek。有些Stream可能only支持順序訪問(如socket和pipe stream),從頭到尾依次訪問。 |
前面已經提到過,Stream 分為:text I/O ,binary I/O ,raw I/O(即無buffer I/O) |
這裡不以文件對象類型來分類方法了,具體實現參考官檔 :
- close() flush 並 關閉Stream,相當於Stream 和 真實i/o設備 斷開。但是文件對象還存在。不能再進行i/o操作了。
- fileno() 返回Stream使用的底層文件描述符。如果沒有報出異常。
- flush() Flush buffers 中的數據到i/o設備中。對只讀或這non-blocking Stream是不起作用的。
- isatty() 如果Stream的i/o設備是一個交互終端,返回True。
- readable() 如果Stream是可讀的,那麼返回True
- readline(size=-1) 讀取一行並返回該行,size指定了的話,返回對應的位元組數。需要註意的是,對於二進位已b’\n’為行界定(包括b’\n’),對於文本, 已open()的newline參數為界定。
- readlines(hint=-1) 將全部行讀入一個list中並返回該list.hint指定的話,讀取對應行數。最好少用,因為Stream是可迭代的,全取出來的話對記憶體消耗肯能很大。
- seek(offset[,whence]) 改變Stream位置到位元組offset。可以指定起點whence({‘start’:0,’cur’:1,’end’:2} or {‘start’:’SEEK_SET’,’cur’:’SEEK_CUR’,’end’:’SEEK_END’})。文本Stream一般只能已Stream開頭偏移操作。位元組Stream三種都支持。函數返回的都是seek後的絕對位置。
- seekable() 判斷Stream是否支持random access。即seek(),tell(),truncate()。
- tell() 返回當前Stream 位置
- truncate(size=None) Resize the Stream 到指定的size 位元組(),如果本來Stream沒有size大,那麼使用zero-filled零添填充(utf-8對應的就是一個space空格的編碼 )。沒指定,就resize到當前位置,同樣,當前位置如果超過了位元組長度,那麼也用zero-filled填充。大多系統是zero-filled,不排除其它填充。同時,truncate()操作不影響Stream的位置,說明瞭seek的訪問範圍不是Stream的長度,可以超出其長度,即就算Stream只有兩個位元組,seek也可以到3個位元組處,也可以到100個位元組處。 返回值是resize後的位元組數。
- writable() 判定Stream是否可寫,即,write()和truncate()兩個寫操作。
- writelines(lines) 寫一個 list of lines to the Stream。Line separators are not added,so it is usaul for each of the lines provided to have a line separator at the end.就是,函數不會給每個元素後添加newline符。
- read(size = -1) 讀取指定size位元組並return讀取的位元組。還分交互io還是非交互io.
Stream對象都是一個context manager,也是一個可迭代對象。
文件對象都是上下文管理器,能夠用於with語法中。
with open('file','r') as fp: passwith語句執行完畢後,自動關閉文件對象。
文件對象可迭代,用於for語句
TextStream和BufferedStream ,前者如果open指定了已指定newline符。後者已b’\n’字元定界行
理論後,實踐操作
讀取文件
#先創建文件 with open('test.txt','x') as fp: fp.write('Hello,world!\n') fp.write('Second Line!') #進行read,readline,readlines和seek操作 fp1 = open(r'test.txt','r') print(fp1.read()) fp1.seek(0) print(fp1.readline()) print(fp1.readline()) print(fp1.readline()) fp1.seek(0) for line in fp1: print(line) fp1.seek(0) print(fp1.readlines()) fp1.close() #已二進位讀 with open(r'test.txt','rb') as fp2: for line in fp2: print(line) fp2.seek(0) print(fp2.read()) fp2.seek(0) print(fp2.readline()) print(fp2.readlines()) read接受的參數是位元組,readline也是,readlines是行數。寫文件,有三種模式’w’,’x’,’a’
with open(r'test.txt','w+') as fp3: fp3.write("Hello,China!") fp3.seek(6) fp3.write("Franch") fp3.seek(0) print(fp3.read()) # 'Hello,Franch' fp3.flush() with open('test.txt','a') as fp4: print(fp4.tell()) # 12 fp4.write("\nHello,China!") fp4.seek(0) fp4.write("\nHello,Japan!") print(fp4.tell()) # 36修改操作,修改要麼全部數據讀入記憶體,在回寫覆蓋。要麼一單位一單位讀,一單位一單位修改,一單位一單位寫入另一個新文件,最後rename。
需求:文件test.txt 的Hello全部替換為 Nice to meet you
with open('test.txt','r') as fp1, open('test.txt.new','w') as fp2: cnt = 0 for line in fp1: if 'Hello' in line: newline = line.replace('Hello','Nice to meet you') cnt += 1 else: newline = line fp2.write(newline) print(cnt)
python I/O 模塊的結構是:IOBase 是頂層抽象
RawI/O就是低級的訪問底層的OS設備或API,不會嘗試將數據裝入高級的單元中()
BufferedIOBase 位元組Stream的基礎類,支持各種類型buffering.
。。。只有參考官方文檔->Generic Operating System Services->io