python的文件操作


剛剛學完文件操作,現學現賣,這就整理起來咯。文件的操作,歸根結底就只有兩種:打開文件、操作文件

一、打開文件:文件句柄 = open('文件路徑', '模式')

python中打開文件有兩種方式,即:open(...) 和  file(...),本質上前者在內部會調用后者來進行文件操作,在這里我們推薦使用open,解釋

二、操作文件

操作文件包括了文件的讀、寫和關閉,首先來談談打開方式:當我們執行 文件句柄 = open('文件路徑', '模式') 操作的時候,要傳遞給open方法一個表示模式的參數:

打開文件的模式有:

  • r,只讀模式(默認)。
  • w,只寫模式。【不可讀;不存在則創建;存在則刪除內容;】
  • a,追加模式。【可讀;   不存在則創建;存在則只追加內容;】

"+" 表示可以同時讀寫某個文件

  • r+,可讀寫文件。【可讀;可寫;可追加】
  • w+,先寫再讀。【這個方法打開文件會清空原本文件中的所有內容,將新的內容寫進去,之后也可讀取已經寫入的內容】
  • a+,同a

"U"表示在讀取時,可以將 \r \n \r\n自動轉換成 \n (注意:只能與 r 或 r+ 模式同使用)

  • rU
  • r+U
  • rbU
  • rb+U

"b"表示處理二進制文件(如:FTP發送上傳ISO鏡像文件,linux可忽略,windows處理二進制文件時需標注)

  • rb
  • wb
  • ab

 以下是file操作的源碼解析:

  1 class file(object):  2  3 def close(self): # real signature unknown; restored from __doc__  4  關閉文件  5  6 """close() -> None or (perhaps) an integer. Close the file.  7  8  Sets data attribute .closed to True. A closed file cannot be used for  9  further I/O operations. close() may be called more than once without  10  error. Some kinds of file objects (for example, opened by popen())  11  may return an exit status upon closing.  12 """  13  14 def fileno(self): # real signature unknown; restored from __doc__  15  文件描述符  16  17 """fileno() -> integer "file descriptor".  18  19  This is needed for lower-level file interfaces, such os.read(). """  20  21 return 0  22  23 def flush(self): # real signature unknown; restored from __doc__  24  刷新文件內部緩沖區  25  26 """ flush() -> None. Flush the internal I/O buffer. """  27  28 pass  29  30 def isatty(self): # real signature unknown; restored from __doc__  31  判斷文件是否是同意tty設備  32  33 """ isatty() -> true or false. True if the file is connected to a tty device. """  34  35 return False  36  37 def next(self): # real signature unknown; restored from __doc__  38  獲取下一行數據,不存在,則報錯  39  40 """ x.next() -> the next value, or raise StopIteration """  41  42 pass  43  44  45  46 def read(self, size=None): # real signature unknown; restored from __doc__  47  讀取指定字節數據  48  49 """read([size]) -> read at most size bytes, returned as a string.  50  51  If the size argument is negative or omitted, read until EOF is reached.  52  Notice that when in non-blocking mode, less data than what was requested  53  may be returned, even if no size parameter was given."""  54  55 pass  56  57 def readinto(self): # real signature unknown; restored from __doc__  58  讀取到緩沖區,不要用,將被遺棄  59  60 """ readinto() -> Undocumented. Don't use this; it may go away. """  61  62 pass  63  64  65 def readline(self, size=None): # real signature unknown; restored from __doc__  66  僅讀取一行數據  67 """readline([size]) -> next line from the file, as a string.  68  69  Retain newline. A non-negative size argument limits the maximum  70  number of bytes to return (an incomplete line may be returned then).  71  Return an empty string at EOF. """  72  73 pass  74  75 def readlines(self, size=None): # real signature unknown; restored from __doc__  76  讀取所有數據,並根據換行保存值列表  77  78 """readlines([size]) -> list of strings, each a line from the file.  79  80  Call readline() repeatedly and return a list of the lines so read.  81  The optional size argument, if given, is an approximate bound on the  82  total number of bytes in the lines returned. """  83  84 return []  85  86  87  88 def seek(self, offset, whence=None): # real signature unknown; restored from __doc__  89  指定文件中指針位置  90 """seek(offset[, whence]) -> None. Move to new file position.  91  92  Argument offset is a byte count. Optional argument whence defaults to  93  0 (offset from start of file, offset should be >= 0); other values are 1  94  (move relative to current position, positive or negative), and 2 (move  95  relative to end of file, usually negative, although many platforms allow  96  seeking beyond the end of a file). If the file is opened in text mode,  97  only offsets returned by tell() are legal. Use of other offsets causes  98  undefined behavior.  99  Note that not all file objects are seekable. """ 100 101 pass 102 103 104 105 def tell(self): # real signature unknown; restored from __doc__ 106  獲取當前指針位置 107 108 """ tell() -> current file position, an integer (may be a long integer). """ 109 pass 110 111 112 def truncate(self, size=None): # real signature unknown; restored from __doc__ 113  截斷數據,僅保留指定之前數據 114 115 """ truncate([size]) -> None. Truncate the file to at most size bytes. 116 117  Size defaults to the current file position, as returned by tell().“"" 118 119  pass 120 121 122 123  def write(self, p_str): # real signature unknown; restored from __doc__ 124  寫內容 125 126 """write(str) -> None. Write string str to file. 127 128 Note that due to buffering, flush() or close() may be needed before 129 the file on disk reflects the data written.""" 130 131  pass 132 133  def writelines(self, sequence_of_strings): # real signature unknown; restored from __doc__ 134  將一個字符串列表寫入文件 135 """writelines(sequence_of_strings) -> None. Write the strings to the file. 136 137 Note that newlines are not added. The sequence can be any iterable object 138 producing strings. This is equivalent to calling write() for each string. """ 139 140  pass 141 142 143 144  def xreadlines(self): # real signature unknown; restored from __doc__ 145  可用於逐行讀取文件,非全部 146 147 """xreadlines() -> returns self. 148 149  For backward compatibility. File objects now include the performance 150 optimizations previously implemented in the xreadlines module. """ 151 152  pass 
file Code

針對上面源碼中的個方法,可以具體看一下在實際操作中的用例:

obj1 = open('filetest.txt','w+')
obj1.write('I heard the echo, from the valleys and the heart\n')
obj1.writelines(['Open to the lonely soul of sickle harvesting\n',
                 'Repeat outrightly, but also repeat the well-being of\n',
                 'Eventually swaying in the desert oasis'])
obj1.seek(0)
print obj1.readline()
print obj1.tell()
print obj1.readlines()
obj1.close()

我們以‘w+’的打開方式為例,write是向文件中寫入一個字符串,而writelines是想文件中寫入一個字符串數組。seek(0)方法是將指針指向其實位置,因為在寫的過程中,指針的標記是隨着寫入的內容不斷后移的,seek方法可以將指針移動到指定位置,而這個時候就指向0位置,從這個位置開始讀,就可以讀到剛剛寫入的所有內容了;readline()是從指針位置讀取一行,所以在這里,執行readline會將剛剛寫入文件中的第一行讀取出來;tell是指出指針當前的位置,這個時候執行tell()方法,指針指向了第二行的起始位置;之后的readlines方法,則會將文件當前指針之后的剩余內容按行讀入數組中。下圖是程序執行后文件和控制台的結果:

盡管剛剛使用'w+'的方式打開文件,但是事實上這種打開方式在文件處理中並不常用,曾一度被我們老師評為‘無意義’,因為用‘w+’方法會清空原文件里所有的東西~

上面一口氣介紹了那么多方法,讓我們有了一個籠統的概念,接下來把這些方法們各功能拿出來對比下:

寫文件操作

write,writelines,相比於那些五花八門的讀方法,寫方法就單純的多了,只有wite和writelines兩種。看下面的例子和寫入的結果,其實write方法和writelines方法都差不多,只不過一個接受的參數是list格式,一個接受的參數是字符串格式而已。這里使用的時候要注意換行符。

1 obj1 = open('E:\PythonL\\11-8\\filetest.txt','r')
2 obj1 = open('filetest.txt','w+')
3 obj1.write('I heard the echo, from the valleys and the heart\nOpen to the lonely soul of sickle harvesting\n')
4 obj1.writelines([
5                  'Repeat outrightly, but also repeat the well-being of\n',
6                  'Eventually swaying in the desert oasis'
7                  ])

剛剛我們使用write和writelines方法向文件里寫入了泰戈爾的一段小詩,結果如下:

I heard the echo, from the valleys and the heart
Open to the lonely soul of sickle harvesting
Repeat outrightly, but also repeat the well-being of
Eventually swaying in the desert oasis

讀文件操作

我們以上面這個文件為例,來說說讀文件:

首先來看一下直接讀取文件中所有內容的方法read和readlines,從下面的結果來看就知道這兩種方法一個返回列表,一個是返回字符串,和上面的write方法相對應:

1 #readline方法
2 obj1 = open('E:\PythonL\\11-8\\filetest.txt','r')
3 print 'readlines:',obj1.readlines()5 #readline方法
6 print "read:",obj1.read()
1 readlines: ['I heard the echo, from the valleys and the heart\n', 'Open to the lonely soul of sickle harvesting\n', 'Repeat outrightly, but also repeat the well-being of\n', 'Eventually swaying in the desert oasis']
readlines result
1 read: I heard the echo, from the valleys and the heart
2 Open to the lonely soul of sickle harvesting
3 Repeat outrightly, but also repeat the well-being of
4 Eventually swaying in the desert oasis
View Code

readlines和read方法雖然簡便好用,但是如果這個文件很龐大,那么一次性讀入內存就降低了程序的性能,這個時候我們就需要一行一行的讀取文件來降低內存的使用率了。

readline,next,xreadlines:用來按行讀取文件,其中需要仔細看xreadlines的用法,因為xreadlines返回的是一個迭代器,並不會直接返回某一行的內容

需要注意的是,盡管我把這一大坨代碼放在一起展示,但是要是真的把這一大堆東西放在一起執行,就會報錯(ValueError: Mixing iteration and read methods would lose data),具體的原因下面會進行解釋。

 1 obj1 = open('E:\PythonL\\11-8\\filetest.txt','r')  2 #readline方法  3 print "readline:",obj1.readline()  5 #readline方法  6 print "next:",obj1.next()  8 #readline方法  9 r = obj1.xreadlines() 10 print 'xreadlines:',r.next() 12 #readline方法 13 print 'readlines:',obj1.readlines() 15 #readline方法 16 print "read:",obj1.read() 

 先展示一下執行上面這些程序的結果好了: 

左側是代碼,右側是相應的執行結果。這里先展示readline,next,xreadlines這三個方法。

1 readline: I heard the echo, from the valleys and the heart
2 
3 next: Open to the lonely soul of sickle harvesting
4 
5 xreadlines: Repeat outrightly, but also repeat the well-being of
read result

這里要補充一點,xreadlines方法在python3.0以后就被棄用了,它被for語句直接遍歷漸漸取代了:

 1 obj1 = open('filetest.txt','r')
 2 for line in obj1:
 3     print line
 4 
 5 運行結果:
 6 I heard the echo, from the valleys and the heart
 7 
 8 Open to the lonely soul of sickle harvesting
 9 
10 Repeat outrightly, but also repeat the well-being of
11 
12 Eventually swaying in the desert oasis

文件中的指針

看完了文件的讀寫,文件的基本操作我們就解決了,下面介紹文件處理中和指針相關的一些方法: seek,tell,truncate

1 obj1 = open('filetest.txt','w+')
2 obj1.write('I heard the echo, from the valleys and the heart\n'
3 'Open to the lonely soul of sickle harvesting\n')
4 print '1.tell:',obj1.tell()
5 obj1.writelines([
6                  'Repeat outrightly, but also repeat the well-being of\n',
7                  'Eventually swaying in the desert oasis'
8                  ])
9 print '2.tell:',obj1.tell()

首先看tell,tell的作用是指出當前指針所在的位置。無論對文件的讀或者寫,都是依賴於指針的位置,我們從指針的位置開始讀,也從指針的位置開始寫。我們還是寫入之前的內容,在中間打印一下tell的結果。執行代碼后結果如下:

1.tell: 96
2.tell: 188

接下來再看一下seek的使用:

1 obj1 = open('E:\PythonL\\11-8\\filetest.txt','r')
2 print "next:",obj1.next(),'tell1:',obj1.tell(),'\n'
3 obj1.seek(50)
4 print "read:",obj1.read(),'tell2:',obj1.tell(),'\n'
next: I heard the echo, from the valleys and the heart
tell1: 188 

read: Open to the lonely soul of sickle harvesting
Repeat outrightly, but also repeat the well-being of
Eventually swaying in the desert oasis tell2: 188 
seek use

從顯示的執行結果來看這個問題,我們在使用next讀取文件的時候,使用了tell方法,這個時候返回的是188,指針已經指向了tell的結尾(具體原因在下面解釋),那么我們執行read方法,就讀不到內容了,這個時候我們使用seek方法將指針指向50這個位置,再使用中read方法,就可以把剩下的內容讀取出來。
在看一個關於truncate的例子:

 1 obj1 = open('filetest.txt','r+')
 2 
 3 obj1.write('this is a truncate test,***')
 4 obj1.seek(0)
 5 print 'first read:\n',obj1.read()
 6 
 7 obj1.seek(0)
 8 obj1.write('this is a truncate test')
 9 obj1.truncate()
10 obj1.seek(0)
11 print '\nsecond read:\n',obj1.read()
1 first read: 2 this is a truncate test,***valleys and the heart 3 Open to the lonely soul of sickle harvesting 4 Repeat outrightly, but also repeat the well-being of 5 Eventually swaying in the desert oasis 6 7 second read 8 this is a truncate test
truncate result

有上面的打印結果我們可以知道,在文件進行寫操作的時候,會根據指針的位置直接覆蓋相應的內容,但是很多時候我們修改完文件之后,后面的東西就不想保留了,這個時候我們使用truncate方法,文件就僅保存當前指針位置之前的內容。我們同樣可以使用truncate(n)來保存n之前的內容,n表示指針位置。

with操作文件

為了避免打開文件后忘記關閉,可以通過管理上下文,即:with open('文件路徑','操作方式') as 文件句柄:

1 #使用whith打開可以不用close
2 with open('E:\PythonL\\filetest.txt','r') as file_obj:
3     file_obj.write('')
4 
5 #在Python 2.7 后,with又支持同時對多個文件的上下文進行管理,下例為同時打開兩個文件
6 #with open('E:\PythonL\\filetest1.txt','r') as file_obj1,open('E:\PythonL\\filetest2.txt','w') as file_obj2:'''

容易犯的錯誤:

ValueError: Mixing iteration and read methods would lose data

我在操作文件的過程中遇到過這樣一個問題,從字面上來看是說指針錯誤,那么這種問題是怎么產生的呢?我發現在使用next或者xreadlines方法之后再使用read或readlines方法就會出現這種錯誤,原因是next或者xreadlines包括我們平時常用的for循環讀取文件的方式,程序都是在自己內部維護了一個指針(這也解釋了我們使用這些方法的時候再用tell方法拿到的指針都是指向了的文件末尾,而不是當前獨到的位置),所以如果我們要先使用上述的next或者xreadlines方法讀取一行,然后再用read或readlines方法將剩余的內容讀到就會報錯。

解決方案:

這個時候有兩種解決方案:

第一種,在讀取一行后,用seek指定指針的位置,就可以繼續使用其他方法了

第二種,使用readline方法,這個方法沒有內部維護的指針,它就是辣么單純的一行一行傻傻的讀,指針也就傻傻的一行一行往下移動。這個時候你也可以使用tell方法追蹤到指針的正確位置,也可以使用seek方法定位到想定位的地方,配合truncate,wirte等方法,簡直不能更好用一些。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM