一、I/O操作概述
I/O概述:
I/O在計算機中時指Input/Output,也就是Stream的輸入與輸出,我們通常說的輸入與輸出其實在作業系統中都是相對于記憶體而言的,InputStream(輸入流)是指資料從外部(網路、鍵盤、I/O設備)流進記憶體,OutputStream正好與之相反,資料從記憶體流出到外部,程式運行時,資料都是在哎記憶體中駐留,由CPU這個超級快的計算核心來執行,涉及到資料交換的地方就需要IO介面,
IO介面的提供以及高級編程語言中的IO操作的實作:
作業系統十個通用的軟體程式,其通用目的如下:
硬體驅動、行程管理、記憶體管理、網路管理、安全管理、I/O管理
作業系統屏蔽了底層硬體,向上提供通用介面,因此,操作I/O的能力是由作業系統提供的,每一種編程語言都會把作業系統提供的低級C介面封裝起來供開發者使用,Python也不例外,
二、檔案讀寫實作原理和操作步驟
1.檔案讀寫實作原理:
由于操作I/O的能力是由作業系統提供的,且作業系統不允許普通程式直接操作磁盤,所以讀寫檔案時需要作業系統打開一個物件,這個物件通常被稱之為檔案描述符--file descriptor,簡稱fd,這個就是我們在程式中要操作的檔案物件,
通常高級編程語言會提供一個內置的函式,通過接收‘檔案路徑’、‘檔案打開模式’等引數來打開一個檔案物件,并回傳該檔案物件的檔案描述符,因此通過這個函式我們就可以獲取到要操作的檔案物件,在Python中這個函式叫open(),在PHP中叫fopen()
2.檔案讀寫操作步驟:
不同編程語言讀寫檔案的操作步驟大體都一樣,都分為以下幾步:
1)打開檔案,獲取檔案描述符;
2)操作檔案描述符--讀/寫;
3)關閉檔案,
3.需要注意的是:
檔案讀寫操作完成后,應該及時關閉,一方面,檔案物件會占用作業系統的資源,另一方面,作業系統對同一時間能夠打開的檔案描述符的數量是有限的,在linux作業系統上可以通過ulimit -n來查看這個現實數量,如果不能及時關閉檔案,還可能造成資料丟失,因為將資料寫入檔案時,作業系統不會立即把資料寫入磁盤,而是先把資料放到記憶體快取區異步寫入磁盤,當呼叫close方法時,作業系統才會保證把沒有寫入磁盤的資料全部寫入到磁盤,否則可能會丟失資料,
三、Python3中檔案打開模式
open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)
打開檔案的引數通常有:檔案路徑名稱、mode引數(即打開模式)、編碼模式...
這里需要搞清楚的就是mode引數,也就是我們使用什么模式打開一個檔案:
Python3原始碼中時這樣解釋的:
Python3原始碼檔案其實對檔案的打開模式進行了詳細的英文闡述,這里非常建議大家自己打開builtins.py檔案自行查看,我相信研究看懂的遠遠比看別人寫的文章描述的更加深刻,
這里只是粘貼一部分打開模式的簡單描述部分:
========= ===============================================================
Character Meaning
--------- ---------------------------------------------------------------
'r' open for reading (default)
'w' open for writing, truncating the file first
'x' create a new file and open it for writing
'a' open for writing, appending to the end of the file if it exists
'b' binary mode
't' text mode (default)
'+' open a disk file for updating (reading and writing)
'U' universal newline mode (deprecated)
========= ===============================================================
接下來我們隊幾個常見且重要的模式進行中文決議:
|
打開模式
|
描述
|
|
r
|
以只讀模式打開檔案,并將檔案指標指向檔案開頭;如果檔案不存在則報錯,
|
|
w
|
以只寫模式打開檔案,并將檔案指標指向檔案開頭;如果檔案存在則將其情況并寫入,如果檔案不存在則創建
|
|
a
|
以只追加寫模式打開檔案,并將檔案指標指向檔案末尾;如果檔案不存在則創建,
|
|
r+
|
在r的基礎上增加可寫功能
|
|
w+
|
在w的基礎上增加可讀功能
|
|
a+
|
在a的模式上增加可讀功能
|
|
b
|
讀寫二進制檔案(默認是t,表示文本模式),需要與上面幾種模式搭配使用,如:ab,wb,ab
|
| x |
創建一個新檔案再打開它寫入;如果檔案已存在則報錯,
|
思考1:r+、w+和a+都可以對檔案進行讀寫,他們有何區別?
會覆寫當前檔案指標所在位置的字符,如原來檔案內容是“Hello World”,以r+模式打開檔案寫入“hi”則檔案內容變成“hillo World”
|
打開模式
|
詳細描述
|
|
r+
|
會覆寫當前檔案指標所在位置的字符,如原來檔案內容是“Hello World”,以r+模式打開檔案寫入“hi”則檔案內容變成“hillo World”
|
|
w+
|
w+在打開檔案時就會先將檔案內清空,再進行寫入,
|
|
a+
|
該模式只能寫在檔案末尾,也就是在檔案末尾進行追加寫入, |
思考2:為何要定義這些模式?為什么不能像word檔案意義打開它之后既可讀又可寫還可以修改呢?
問題答案參考網上:
跟安全有關,有這種觀點的大部分是做運維的朋友,他們認為這就像linux上的rwx(讀、寫、執行)權限,
跟作業系統內核管理I/O的機制有關,有這種觀點的大部分是做C開發的,特別是與內核相關的開發人員,為了提高讀寫速度,要寫入磁盤的資料會先放進記憶體緩沖區,之后再回寫,由于可能會同時打開很多檔案,當要回寫資料時,需要遍歷以打開的檔案判斷是否需要回寫,他們認為如果打開檔案時指定了讀寫模式,那么需要回寫時,只要去查找以“可寫模式”打開的檔案就可以了,
四、Python檔案操作實體
讀取檔案open_test.py,該檔案的字符編碼為utf-8
![]()
Python3實作:
![]()
輸出結果:
![]()
這里需要注意一點就是,我們在讀寫檔案時候,特別是在讀的時候大部分情況,如果檔案路徑不正確或者檔案不存在,也就是找不到檔案,又或者是在進行檔案操作時候出現I/O錯誤,就會報錯,此時如果要保證代碼的健壯性最好加上try...finally來實作錯誤捕捉以及及時關閉檔案物件(優化代碼如下):
![]()
輸出結果:
![]()
上面關閉檔案的代碼有時候很容易忘記,所以我們接下來使用Python with方法來完成自動關閉檔案:
![]()
輸出結果:
![]()
可以看到在with陳述句中檔案時沒有關閉的,只有出了with陳述句后檔案會自動關閉
關于Python with背景關系管理的用法可以查看文章了解: https://www.cnblogs.com/suguangti/p/11123515.html
五、Python檔案讀取相關方法
對檔案的讀取操作需要將檔案中的資料加載到記憶體中,而在上面所用到的read()方法會一次性的把檔案中所有的內容全部加載到記憶體中,這顯然是不合理的,如果我們讀取的是一個大檔案,有幾個G的檔案時,必然會耗光機器的記憶體或者直接報錯,所以肯定有一些其他的讀取方法來解決:
|
方法
|
描述
|
| read() |
一次性讀取檔案所有內容
|
|
read(size)
|
每次最多讀取指定長度內容,在Python2中size指定是位元組長度,而在Python3中size指定為字符長度
|
|
readlines()
|
一次性讀取檔案所有內容,按行回傳一個list
|
|
readline()
|
每次只讀取一行內容
|
此外還有兩個關于檔案指標位置的方法:
|
方法
|
描述
|
|
seek()
|
將檔案指標移動到指定位元組位置
|
|
tell()
|
|
實體一:
輸出結果:
實體二:
輸出結果:
readlines()方法跟read()方法一樣,都會消耗大量記憶體空間,
實體三:
或者:
輸出結果:
解決列印每一行換行符問題:
方法一:
方法二:
輸出結果:
六、檔案操作其他方法
|
方法
|
描述
|
| flush() |
重繪緩沖區資料,將緩沖區中的資料立刻寫入檔案
|
|
next()
|
回傳檔案下一行,這個方法也是file物件實體可以被當作迭代器使用的原因
|
|
truncate(size)
|
截取檔案中指定位元組數的內容,并覆寫保存到檔案中,如果不指定size引數,則檔案將被清空;Python2中無回傳值,Python3回傳新檔案的內容位元組數
|
|
write(str)
|
將字符寫入檔案,沒有回傳值
|
|
writelines(sequence)
|
向檔案寫入一個字串貨一個字串串列,如果字串串列中元素需要換行要自己加入換行符
|
|
fileno()
|
回傳一個整型的檔案描述符,可以用于一些底層I/O操作上(如os模塊的read方法)
|
|
issatty()
|
判斷檔案是否被連接到一個虛擬終端,是則回傳True,否則回傳False
|
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/156497.html
標籤:Python
上一篇:Python練習題4.6輸出前 n 個Fibonacci數
下一篇:Python練習題4.9查詢水果價格