我愛學 Python 之文件

讀取文件

假設你已經在某個文件夾下建立了 「test.txt」 文件,且裏面有一些內容,那你在當前位置輸入 Python3,進入到交互模式,而後執行下面的操做:this

>>> f = open('test.txt')
>>> for line in f:
...    print(line)
... 
My name is Rocky

I love Python

這裏提醒你們注意一下,若是是在該文件所在的位置啓動的 Python 交互模式,那麼按照上面的方法 open(‘test.txt’) 打開文件,這意味着 test.txt 是在當前文件夾下的,若是要打開其它文件夾下的文件,要使用相對路徑或者絕對路徑來表示,從而讓 Python 能找到那個文件。設計

看上面的例子,open() 一個文件,即生成了一個對象,把這個對象賦值給變量 f,從而讓變量 f 和文件對象之間創建了引用關係,接下來用 for 循環讀取文件中的內容,把讀到的文件中的每行賦值給變量 line (這裏的每行能夠看做是對象),從打印的結果看,每一行與你讀取的文件的每一行是相同的。指針

若是你作完了上述操做,那麼請看下面的操做:code

>>> for line1 in f:
...    print(line1)
... 
>>>

你會奇怪的發現,居然什麼也沒有,是否是出錯了?其實並無,由於以前已經讀取過一次文件的內容了,而且到了文件的末尾,再重複操做,就要從文章的末尾開始讀了,固然就沒有什麼東西了,在 Python 中並不會認爲這是錯誤。若是你想再次讀取的話,請從新 open() 一下文件。對象

建立文件

讀文件只是針對文件的操做之一,還有建立文件。blog

在上面讀文件的時候,咱們打開的是一個已經存在的文件,那麼如何建立一個新文件呢?請看下面的操做:教程

>>> new_file = open('new.txt','w')
>>> new_file.write('this is a new file')
18
>>> new_file.close()

new_file = open(‘new.txt’,’w’) 意味着在當前的目錄下建立了一個名爲 new_file 的文件,該文件爲 「w」 打開模式。圖片

new_file.write('this is a new file’) 則是向已創建的新文件中寫入 「this is a new file」,而且返回的是寫入字符串的長度。內存

new_file.close() 則是關閉當前文件,而後將寫入的話保存到文件中。字符串

由上面的例子咱們能夠看出,建立文件咱們一樣用的是 open() ,可是多了個 「w」 ,這是告訴 Python 用什麼模式打開文件。在 Python 中,能夠用不少不一樣的模式打開文件,請看下圖(截圖來自菜鳥教程):
在這裏插入圖片描述
從上圖中能夠看出,不一樣的模式下打開文件能夠進行不一樣的讀寫操做,若是什麼都不寫的話,默認爲以只讀(r)的方式打開文件。

使用 with 自動關閉文件

在前面的操做中咱們能夠看到,在對文件進行寫操做以後,要執行關閉文件的操做,執行關閉文件的操做是爲了將寫入的內容保存到文件中,若是不進行 close() 操做的話,那麼新寫入的內容將不會被保存。

Python 早就知道會有不少馬大哈們會忘記 close()的操做,因此它建立了一種簡單的方法,這就是 with,它會實現自動關閉文件,看!Python 是多麼的人性化!請看下面的操做:

>>> new_file.close()
>>> with open('new.txt','a') as f:
...     f.write(‘\nwith is good good good.')
... 
23

在這裏 with 實際上是要發起一個語句的,這裏兼具了後面我會講的 try/finally,便可以在遇到異常的時候發出提醒,此處暫時先不講,等之後我再細說,咱們先學會用 with。

>>> with open('new.txt') as f:
...    print(f.read())
... 
this is a new file
with is good good good.

看吧,在 with 中咱們能夠放輕鬆的扔掉 close 了,上面例子中用到的 read() 方法,在明天的文章中我會講到。

文件的屬性

不少時候,咱們須要獲取一個文件的有關屬性,好比文件的建立日期,修改日期等等,在 Python 中有一個專門針對時間設計的模塊 -- time。請看下面的操做:

>>> import time
>>> time.localtime()
time.struct_time(tm_year=2018, tm_mon=7, tm_mday=25, tm_hour=21, tm_min=49, tm_sec=32, tm_wday=2, tm_yday=206, tm_isdst=0)

其實還有一種辦法能夠查看文件的這些屬性,就是 os 模塊裏的 stat,在這裏我就是提一嘴,以後講到 os 模塊的時候再仔細說。

讀取文件的內容

由於文件的對象是可迭代的,因此可以用open() 打開文件,因此用 for 循環能夠將文件的內容讀出來。我在前面的文章說過,能夠用 dir() 查看文件對象的屬性和方法,當你看了之後你會發現有 3 個方法 read / readline / readlines,單單從名稱上看,它們應該和讀有關係,事實上確實是這樣的,可是它們 3 個又有些微的差異。

1.read()

文件對象的 read() 方法,其實完整的寫出來實際上是 read( size ),只不過裏面的參數能夠省略,若是不省略,則讀取文件中的 size 個字符並返回一個字符串;若是省略的話,則讀取文件對象的字符知道 EOF,EOF == End - of - file。

>>> f = open('new.txt')
>>> f.read(10)
'this is a '
>>> f.read()
'new filewith is good good good.’

若是你是按照上述的例子依次進行操做的,就會在 f.read() 後出現上述的結果,這主要是由於在前面已經 read(12) 了,指針已經移動到了第 12 個字符後面。

2.readline() & readlines()

readline() 就是它表面的意思,逐行讀取文件的內容。

>>> f = open('new.txt')
>>> f.readline()
'this is a new filewith is good good good.'
>>> f.readline()
''

每次執行 readline() 的時候它只讀一行,直到最後一行,若是還執行 readline() 的話,它不會報錯,返回的是空字符串。

一樣也是有 readline(size) 的,若是給 readline(size) 參數,則讀取相應行的 size 個字符,有興趣的能夠本身試一下。

還有一個是 readlines(),它的做用是將文件中各行讀出來,放到一個列表中返回。

>>> f = open('test.txt')
>>> f.readlines()
['My name is Rocky\n', 'I love Python’]

既然返回的是一個列表,那麼就能用 for 循環讀取列表元素,再觀察一下能夠發現,列表中的每一個元素都是文件的一行,而且是字符串。

>>> f = open('test.txt')
>>> for line in f.readlines():
...    print(line)
... 
My name is Rocky

I love Python

這個是否是讓你以爲和上面文件的 for 循環很相似?

>>> f = open('test.txt')
>>> for line in f:
...    print(line)
... 
My name is Rocky

I love Python

乍一看兩種方式好像沒有什麼區別,其實這兩種方式是不一樣的。在 for line in f 中,並無將文件中因此的行都讀入內存,而 for line in f.readlines() 中先執行了 f.readlines(),在內存中有一個列表,列表中包含了全部文件的行,這就是兩種方式的區別。

大文件的讀取

上面的三個讀取文件內容的方法 read 和 readlines 都是一次性將所有的內容讀入內存,若是文件不是很大的話,這種作法可以保證讀取的速度,可是若是文件內容很大,大到差很少內存那麼大或者更大的時候,就不能這麼作了。可是 Python 早就替你考慮到了,Python 中有一個 fileinput 模塊,可使用它來操做。

>>> import fileinput
>>> for line in fileinput.input('test.txt'):
...    print(line,end = '')
... 
My name is Rocky
I love Python

由於我沒有大的文件,只是爲了演示一下這個模塊的用法,對於這個模塊更多的內容,能夠在交互模式下用 dir() 去查看。

seek

不知道你有沒有奇怪過在以前的演示中,每次都要作 f = open(‘***’) 相似的操做,不然就會出現下面的狀況:

>>> f = open('test.txt')
>>> for line in f:
...    print(line)
... 
My name is Rocky

I love Python
>>> for line in f:
...    print(line)
... 
>>>

是否是發現,當咱們第二次循環文件的時候,既沒有報錯,也沒有顯示文件的內容,相似的現象在前面的 readline 中也出現過,這是由於讀取文件的時候,有指針隨着運動,當讀取結束時,指針就到了相應的位置。

當指針結束運動時,可使用 tell() 告訴咱們當前指針的位置。

>>> f = open('test.txt')
>>> f.readline()
'My name is Rocky\n'
>>> f.tell()
17

如今咱們來看 seek() 的能力,它可以根據偏移量來移動指針。

>>> f.seek(0)
0

上面的意思是將指針移動到文件的開始,若是用 f.readline() 讀取的話,如今輸出的應該是文件的第一行:

>>> f.readline()
'My name is Rocky\n’

其實還能夠操縱指針到任何一個位置,請看下面的操做:

>>> f.seek(10)
10
>>> f.tell()
10

f.seek(10) 就是將位置定位到從開頭算起到第 10 個字符後面,這時候若是使用 readline 的話,讀取的是從當前位置到行末的字母。

寫在以後

更多內容,歡迎關注公衆號「Python空間」,期待和你的交流。

相關文章
相關標籤/搜索