——文件操作——
一般我們對文件操作惊完,大體來說有三個步驟:
(1)在目錄中找到這個文件稽莉,并打開它;
(2)對文件進(jìn)行操作坛猪;
(3)關(guān)閉文件。
在Python中也是類似的皂股,打開文件open(“文件名”)墅茉,Python會自動找有沒有這個文件,然后我們通過.read()把文件里的數(shù)據(jù)讀取出來呜呐,賦給一個變量就斤,然后進(jìn)行打印。這里注意一點蘑辑,我們在打開文件時要聲明一下字符級洋机,因為Windows顯示用的是“gbk”的編碼方案,而python用的是“utf-8”洋魂,所以在打開文件時绷旗,要告訴程序,用“utf-8”進(jìn)行顯示副砍,不然則會出現(xiàn)“UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 2: illegal multibyte sequence”這樣的錯誤衔肢。
但是呢,這樣寫其實是不規(guī)范的豁翎,因為你讀出來的是文件里面的所有數(shù)據(jù)內(nèi)容角骤,要是操作的話,操作的是數(shù)據(jù)心剥,沒有辦法對文件本身進(jìn)行操作邦尊。文件在打開的時候在內(nèi)存里存的是一個內(nèi)存對象,我們要把這個內(nèi)存對象賦給一個變量优烧,這樣我們在對文件進(jìn)行操作的時候蝉揍,就可以對這個變量進(jìn)行操作,變量一般為“f”匙隔,叫做“文件句柄”疑苫,文件句柄對于打開的文件是唯一的識別標(biāo)志熏版。文件句柄一般包括:文件名、大小捍掺、字符級撼短、在硬盤上的起始位置。
我們現(xiàn)在對文件讀取一遍之后挺勿,賦值給data曲横,然后再對文件進(jìn)行一遍讀取底洗,賦值給data1搬俊,我們看一下會有什么樣的結(jié)果?
可以看到馅闽,其實data1什么內(nèi)容也沒有蚊丐,這是為什么呢熙参?因為python的程序是依次往下執(zhí)行的,第一遍讀取了之后麦备,位置就停留在文件“song”的末尾孽椰,在執(zhí)行第二次讀取的時候,從上次停留的位置凛篙,也就是文件的末尾開始讀取黍匾,所以什么內(nèi)容也沒有讀取到。
我們讀完文件之后呛梆,再來看一下寫锐涯,語法:f.write()
報錯了,顯示文件是不可寫的填物,這是什么原因呢纹腌?
因為在打開文件的時候,我們的寫法并不規(guī)范融痛,其中還應(yīng)該有一項內(nèi)容是“文件的模式”壶笼,如果我們什么也不寫,就默認(rèn)是只讀模式“r”雁刷。
——文件的模式——
①“r”覆劈,這是只讀模式。
只讀模式是不可以寫的沛励。
②“w”责语,這是只寫模式。
首先目派,只寫模式是不可以讀的坤候。
只寫模式里面,打開文件實際上是創(chuàng)建一個新的文件企蹭。
可以看到白筹,我們open的是“song1”智末,之前并沒有這個文件,然后就自動創(chuàng)建了一個新的文件“song1”徒河。
若是我們打開的是“song”系馆,之前有的,會把以前的內(nèi)容全部清空顽照,然后再在里面寫內(nèi)容由蘑。
③“a”,這是追加模式代兵。
若是文件之前存在尼酿,追加模式則是在文件的末尾繼續(xù)接著追加內(nèi)容。
若是文件不存在植影,則是創(chuàng)建一個新的文件裳擎,并且開始寫內(nèi)容。
追加模式中思币,文件也是不可讀的句惯。
——文件的整個讀取——
語法:f.readlines( )
readlines()?方法用于讀取所有行(直到結(jié)束符 EOF)并返回列表,該列表可以由 Python 的 for... in ... 結(jié)構(gòu)進(jìn)行處理支救。如果碰到結(jié)束符 EOF 則返回空字符串。返回列表拷淘,包含所有的行各墨。
注意:這里是讀取所有的行,然后返回的是每行作為一個元素的列表启涯,且每行的后面有一個“\n”贬堵。
我們用Python 的 for... in ... 結(jié)構(gòu)進(jìn)行處理一下,便可以打印整個文件:
我們要是想去掉這個換行结洼,可以用strip:
——文件的部分讀取——
現(xiàn)在我要是想只讀取文件的前三行黎做,應(yīng)該怎么辦?
語法:f.readline( )
readline()?方法用于從文件讀取整行松忍,包括 "\n" 字符蒸殿。如果指定了一個非負(fù)數(shù)的參數(shù),則返回指定大小的字節(jié)數(shù)鸣峭,包括 "\n" 字符宏所。
print(f.readline)重復(fù)的寫三次就可以打印前三行,這里要注意的一點是f.readline后面包含“\n”摊溶,所以打印出來之后爬骤,每一行后面都有一個換行。
如果這么寫莫换,那要是打印前30行霞玄,代碼就相當(dāng)多了骤铃,而且是重復(fù)的。我們可以用for循環(huán)來打涌谰纭:
可以看到惰爬,確實打印了前10行,同樣的每一行結(jié)束都有一個“\n”听隐,所以打印出來每行都有一個換行补鼻。
我們接下來的需求是:當(dāng)我打印到第十行的時候,我不進(jìn)行打印了雅任,我們輸出顯示“------第十行------”风范,這應(yīng)該怎么操作?
我們可以用之前學(xué)過的方法沪么,用enumerate枚舉的方法硼婿,他可以同時打印出每一行及其索引,第十行的索引是9禽车,我們在這時就可以做一個判斷寇漫,當(dāng)索引是“9”的時候,我們就打印“------第十行------”殉摔,其他的我們就打印輸出文件的相應(yīng)行即可州胳。
程序如下:
結(jié)果如下:
enumerate()里面是f.readlines,是文件每一行組成的一個列表逸月,是先把文件轉(zhuǎn)換成一個列表栓撞,然后在進(jìn)行for循環(huán)打印輸出。f.readlines是一次性把文件整個讀進(jìn)去的碗硬,所以只適合讀小文件瓤湘,如果文件過大,可能會撐爆內(nèi)存恩尾,那么我們?nèi)绻且粋€比較大的文件弛说,那應(yīng)該怎么操作?
我們要考慮翰意,每次只讀進(jìn)去一行木人,然后把上一次讀的一行刪掉,這樣讀一行刪一行冀偶,這時候就只占一行的內(nèi)存:
這時候f就變成個了一個迭代器虎囚。
這時候,就沒有索引了蔫磨,我們要是想0實現(xiàn)第十行打印“------第十行------”淘讥,其他打印文件內(nèi)容,我們這時候就要加一個計數(shù)器堤如,采用count計數(shù)即可:
結(jié)果如下: