- 零基礎入門學習Python(第2版)
- 小甲魚
- 7字
- 2019-12-20 12:19:44
第8章 永久存儲
8.1 文件:因為懂你,所以永恒

視頻講解
大多數的程序都遵循著“輸入→處理→輸出”的模型,首先接收輸入數據,然后按照要求進行處理,最后輸出數據。到目前為止,我們已經很好地了解了如何處理數據,然后打印出需要的結果。不過你可能已經“胃口大開”,不再只滿足于使用input接收用戶輸入,使用print輸出處理結果了。你迫切想要關注到系統的方方面面,需要自己的代碼可以自動分析系統的日志,需要分析的結果可以保存為一個新的日志,甚至需要與外面的世界進行交流。
相信大家都曾經有這樣的經歷:在編寫代碼正起勁兒的時候,系統突然藍屏崩潰了,重啟之后發現剛才寫入的代碼都不見了,這時候你就會吐槽這破系統怎么這么不穩定。
在編寫代碼的時候,操作系統為了更快地做出響應,把所有當前的數據都放在內存中,因為內存和CPU數據傳輸的速度要比在硬盤和CPU之間傳輸的速度快很多倍。但內存有一個天生的不足,就是一旦斷電就“沒戲”,所以小甲魚在這里再一次呼吁廣大未來即將成為偉大程序員的讀者們:請養成一個優雅的習慣,隨時使用Ctrl+S快捷鍵保存數據。
Windows以擴展名來指出文件是什么類型,所以相信很多習慣使用Windows的朋友很快就反應過來了,.exe是可執行文件格式,.txt是文本文件,.ppt是PowerPoint的專用格式等,所有這些都稱為文件。
8.1.1 打開文件
在Python中,使用open()這個內置函數來打開文件并返回文件對象:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline= None, closefd=True, opener=None)
open()這個函數有很多參數,但作為初學者,只需要先關注第一個和第二個參數即可。第一個參數是傳入的文件名,如果只有文件名,不帶路徑的話,那么Python會在當前文件夾中去找到該文件并打開;第二個參數指定文件打開模式,如表8-1所示。
表8-1 文件的打開模式

使用open()成功打開一個文件之后,它會返回一個文件對象,拿到這個文件對象,就可以對這個文件“為所欲為”:
>>> # 先在桌面創建一個record.txt的文本文件,內容隨意 >>> f = open(r"C:\Users\goodb\Desktop\record.txt") >>>
沒有消息就是好消息,說明文件被成功打開了。如果出錯了也不要急,是不是直接將上面的路徑給代入了呢?記得要替換為自己桌面的路徑,Python才能成功找到文件。
8.1.2 文件對象的方法
打開文件并取得文件對象之后,就可以利用文件對象的一些方法對文件進行讀取、修改等操作。表8-2列舉了平時常用的一些文件對象方法。
表8-2 文件對象方法

8.1.3 文件的關閉
close()方法用于關閉文件。如果是講C語言編程教學,小甲魚一定會一萬次地強調文件的關閉非常重要。而Python擁有垃圾收集機制,會在文件對象的引用計數降至零的時候自動關閉文件,所以在Python編程里,如果忘記關閉文件并不會造成內存泄漏那么危險的結果。
但并不是說就可以不要關閉文件,如果對文件進行了寫入操作,那么應該在完成寫入之后關閉文件。因為Python可能會緩存寫入的數據,如果中途發生類似斷電之類的事故,那些緩存的數據根本就不會寫入到文件中。所以,為了安全起見,要養成使用完文件后立刻關閉的好習慣。
8.1.4 文件的讀取和定位
文件的讀取方法很多,可以使用文件對象的read()和readline()方法,也可以直接list(f)或者直接使用迭代來讀取。read()是以字節為單位讀取,如果不設置參數,那么會全部讀取出來,文件指針指向文件末尾。tell()方法可以告訴你當前文件指針的位置:

剛才提到的文件指針是啥?可以認為它是一個“書簽”,起到定位的作用。使用seek()方法可以調整文件指針的位置。seek(offset, from)方法有兩個參數,表示從from(0代表文件起始位置,1代表當前位置,2代表文件末尾)偏移offset字節。因此將文件指針設置到文件起始位置,使用seek(0, 0)即可:
>>> f.tell() 284 >>> f.seek(0, 0) 0 >>> f.read(5) '小客服:小' >>> f.tell() 9
注意:
因為1個中文字符占用2字節的空間,所以4個中文加1個英文冒號剛好到位置9。
readline()方法用于在文件中讀取一整行,就是從文件指針的位置向后讀取,直到遇到換行符(\n)結束:
>>> f.readline() '甲魚,有個好評很好笑哈。\n'
此前介紹過列表的強大,什么都可以往里放,這不,也可以把整個文件的內容放到列表中:

對于迭代讀取文本文件中的每一行,有些讀者可能會這么寫:

這樣寫并沒有錯,但給人的感覺就像是你拿酒精燈去燒開水,水是燒得開,不過效率不是很高。因為文件對象自身是支持迭代的,所以沒必要繞圈子,直接使用for語句把內容迭代讀取出來即可:

8.1.5 文件的寫入
如果需要寫入文件,請確保之前的打開模式有'w'或'a',否則會出錯:

然而一定要小心的是:使用'w'模式寫入文件,此前的文件內容會被全部刪除,如圖8-1所示,小甲魚和小客服的對話備份已經不在了。

圖8-1 'w'打開模式會刪除原來的文件內容
如果要在原來的內容上追加,一定要使用'a'模式打開文件。這是血淋淋的教訓,不要問我為什么(想想都是淚啊)!
8.1.6 一個任務

視頻講解
本節要求讀者獨立來完成一個任務,將文件(record2.txt)中的數據進行分割并按照以下規則保存起來:
(1)將小甲魚的對話單獨保存為boy_*.txt文件(去掉“小甲魚:”)。
(2)將小客服的對話單獨保存為girl_*.txt文件(去掉“小客服:”)。
(3)文件中總共有三段對話,分別保存為boy_1.txt、girl_1.txt、boy_2.txt、girl_2.txt、boy_3.txt、girl_3.txt這6個文件(提示:文件中不同的對話間已經使用“=======================================”分割)。
大家一定要自己先動動手再參考答案哦。

事實上可以利用函數封裝得更好看一些:

- 數據科學實戰手冊(R+Python)
- Mastering Spring MVC 4
- Visual C++數字圖像模式識別技術詳解
- C和C++安全編碼(原書第2版)
- VSTO開發入門教程
- C/C++常用算法手冊(第3版)
- Python數據結構與算法(視頻教學版)
- Web Development with MongoDB and Node(Third Edition)
- Building Microservices with .NET Core
- Learning Apache Karaf
- Moodle 3 Administration(Third Edition)
- Mastering PowerCLI
- Professional JavaScript
- Internet of Things with Arduino Cookbook
- 秒懂算法:用常識解讀數據結構與算法