目錄
1、文件讀寫原理和操作步驟
1.1、文件讀寫原理
文件讀寫就是一種常見的io操作,python也應該是封裝操作系統的底層接口,直接提供了文件讀寫相關的操作方法,讀寫文件時需要請求操作系統打開一個對象,(文件描述符:簡寫爲jd)這就是我們在程序中要操作的文件對象
1.2、文件的操作步驟
- 打開文件,獲取文件描述符
- 操作文件描述符,---讀/寫
- 關閉文件
注意事項:
- 文件讀寫操作完成後,要及時的關閉文件。
原因:
因爲,文件對象會佔用系統的資源,另一方面,操作系統對同一時間能打開的文件描述符的數量是有限制的,在linux系統上通過ulimit-n 來查看這個顯示的數量。如果不及時的關閉文件,可能會造成句柄佔用,數據丟失。因爲當將數據寫入文件時,操作系統不會立即把數寫入到磁盤中,而是先把數據存入到內存緩衝區異步寫入磁盤。當調用close方法的時候,操作系統會保證把沒有寫入磁盤的數據全部寫入到磁盤中去,否則丟失數據。
1.3、文件打開模式
1、open方式打開
語法:
open(file,mode="r",encoding=None)
- file:文件名稱,如果代碼和所在的文件是同一個目錄下,則不用重寫書寫路徑,否則如果不在同一個路徑下,需要寫上具體的路徑。
- mode:決定了打開文件的模式,默認是read模式
- encoding:如果不寫則默認爲gbk模式,也就是對應txt的ansi模式。如果寫明utf8,則txt文件中保存也必須是utf8的模式。
示例:
方法1:用open方法打開,需要關閉文件。
#coding=utf-8
fp=open("e://a.txt","r")
str=fp.read()
print(str)
#關閉文件
fp.close()
方法2:用with...open方式打開
with方式打開文件:會默認關閉文件,這種方式比較推薦。
#coding=utf-8
with open ("e:\\a.txt","r",encoding="utf-8") as fp:
for line in fp:
print(line)
注意事項:
1、文件的書寫模式爲:“e:\\a.txt” 或者是r"e:\a.txt"
2、如果讀取utf-8的模式下,有utff類的字樣,需要安裝一個Notepad++,打開文件,將編碼格式轉換 爲:utf-8無Bom格式
問題1:當我不知道該文件的編碼是什麼編碼時,比方用mac本打開,則怎麼判斷???
>>> fp=open("e:\\a.txt","rb")
>>> content=fp.read()
>>> type(content)
<class 'bytes'>
>>> import chardet
>>> chardet.detect(content)
{'encoding': 'UTF-8-SIG', 'confidence': 1.0, 'language': ''}
>>>
問題2:當讀取文件時,最終是用什麼格式來讀取的呢???
>>> fp=open("e:\\a.txt",encoding="utf-8")
>>> content=fp.read()
>>> type(content)
<class 'str'>
>>>
這是因爲:bytes類型只用在內存中或者文件存儲的時候,當讀取文件時,就自動轉換爲str類型了。
1.4、文件操作模式
- r: 只讀模式,並將文件指針指向文件頭, 如果文件不存在,則會報錯。
- w:只寫模式,將文件指針指向文件頭,如果文件存在則將內容清空,如果文件不存在,則
創建
- a:只以追加可寫的模式打開文件,並將文件指針指向文件的尾端;如果文件不存在則創建
- r+:在r的基礎上增加了可寫功能,會覆蓋當前文件指針所在的位置的字符。文件的指針放在
文件的開頭
- w+:在w的基礎上增加可讀功能。在打開文件的時候,就先將文件內容清空 ,如果該文件不
存在,則創建新文件
- a+:在a的基礎上增加了可讀功能。只能寫在文件末尾,文件打開時,是一個追加模式,如
果該文件不存在,則創建新文件用於讀寫。
- b:讀寫二進制數,需要配合使用,如ab,wb
模式 |
r |
r+ |
w |
w+ |
a |
a+ |
讀 |
+ |
+ |
+ |
+ |
||
寫 |
+ |
+ |
+ |
+ |
+ |
|
創建 |
+ |
+ |
+ |
+ |
||
覆蓋 |
+ |
+ |
||||
指針在開始 |
+ |
+ |
+ |
+ |
||
指針在結尾 |
+ |
+ |
練習題:判斷r+、a+、w+是有什麼區別的。
1.41、r+示例
示例:
情況一:當該目錄下沒有該文件時,會報錯
#coding=utf-8
with open ("e:\\c.txt","r+",encoding="utf-8") as fp:
for line in fp:
print(line)
結果:
=========================== RESTART: E:\代碼練習\a.py===========================
Traceback (most recent call last):
File "E:\代碼練習\a.py", line 4, in <module>
fp=open("e://b.txt","r+",encoding="utf-8")
FileNotFoundError: [Errno 2] No such file or directory: 'e://b.txt'
>>>
情況2:當該目錄中有文件時,且該文件有內容,如果直接寫入,則寫入內容在文件的開頭進行覆蓋操作。
程序:
#coding=utf-8
fp=open("e:\\b.txt","r+")
fp.write("hellodwejwekwjewe")
fp.seek(0,0)
print(fp.read())
fp.close()
結果:
============================== RESTART: E:\a.py ==============================
hellodwejwekwjeweiqjiwe
3jksjdkfs
>>>
情況3:當該目錄下有該文件時,怎樣在末尾填寫內容,需要先讀取文件,將光標放在文件末尾
#coding=utf-8
fp=open("e:\\a.txt","a+",encoding="utf-8")
print(fp.read())
print(fp.tell())
fp.write("hello")
print(fp.read())
fp.close()
注意事項:
1)用r+的時候,每次光標都放在開頭,如果要在文章的末尾需要添加內容,需要先讀取文件,將光標放在最後的位置纔可以。
2)所以如果不移動光標到(0,0)的位置,則無法讀取數據。
如果想要讀取內容,則需要一個步驟:fp.seek(0,0)
3)r+()方法可以寫入內容,會覆蓋當前文件指針所在的位置的字符,至於覆蓋幾個,按照python3的字符來計算。在寫入時,通常不建議使用r+()模式。
1.42、w+示例
w+和r+的最大區別,如果文件不存在,則創建一個新文件,不會報錯。
#coding=utf-8
fp=open("e:\\xxxx.txt","w+",encoding="utf-8")
fp.write("我是一朵花\n")
fp.write("我是一棵草\n")
fp.flush()
fp.seek(0,0)
content=fp.readlines()
print(content)
fp.close()
注意: 當寫入文件後,直接讀取,有可能寫入內容讀取不出來,這是因爲寫入後,內容沒有直接在磁盤上,需要刷新一下,或者是關閉文件重新開啓。
1.43、a+的示例
如果文件存在,則光標默認在文件的末尾,a+是追加模式,如果是讀取模式,需要先把光標設置成(0,0)的模式,否則讀取爲空。如果文件不存在,則創建新文件。另外注意,無論光標位於什麼位置,使用a+,寫入的內容都會放在最後的位置。
程序:
#coding=utf-8
fp=open("e:\\xxxx.txt","a+",encoding="utf-8")
print(fp.readline())
#將遊標放在了開始的位置,再進行寫
fp.seek(0,0)
fp.write("xxxxxxxxxxxxxxxx")
fp.flush()
fp.seek(0,0)
content=fp.read()
print(content)
fp.close()
結果:
============================== RESTART: E:\a.py ==============================
我第四朵花
我是一棵草
我第四我是一朵花
我是一棵草
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>>>
1.5、文件讀取相關方法
我們知道,對文件的讀取操作,需要將文件中的數據加載到內存中,我們可以查看python中讀取文件的相關方法:
1.51、讀取文件的相關方法
- read():一次讀取文件的所有內容,返回一個str
- readline():每次只讀取一行內容,包含"\n"字符。
- readline(size):每次最多讀取指定長度的內容,返回一個str,python3中的size指定的是字符長度。
- readlines():一次性讀取所有內容,存放在一個list中。
示例:
在e盤,有一個aa.txt的文件夾
# coding=utf-8
'''aa.txt的保存格式爲ansi,也就是默認的gbk類型'''
#方法1:採用read()方式讀取文件aa.txt
with open("e:\\aa.txt","r") as fp:
content=fp.read()
print(content)
#方法2:採用readline()一行一行的讀取
fp=open("e:\\aa.txt","r")
print(fp.readline())
print(fp.readline())
fp.close()
#方法3:採用readlines()將文件一次讀取完,放在一個列表中
with open("e:\\aa.txt","r") as fp:
content=fp.readlines()
print(content)
#方法4:採用遍歷的方式將文件讀取出來。
with open("e:\\aa.txt","r") as fp:
for line in fp:
print(line)
1.6、文件的寫入操作
1.61、f.write(string)
將string寫入到文件中,然後返回寫入的字符數。
在文件關閉前或者緩衝區刷新前,字符串內容是存儲在緩衝區的,這時文件看不到內容。
示例:
# coding=utf-8
'''aa.txt的保存格式爲ansi,也就是默認的gbk類型'''
#方法1:採用read()方式讀取文件aa.txt
with open("e:\\aa.txt","a+") as fp:
fp.write("將軍行")
fp.flush()
結果:
注意:在寫入時,如果寫入的不是字符串,則會報錯。
1.62、fp.writelines()
把seq(序列)的內容全部寫入到文件中(多行一次性寫入),也不會自動加入換行符。
# coding=utf-8
'''aa.txt的保存格式爲ansi,也就是默認的gbk類型'''
with open("e:\\aa.txt","a+") as fp:
num=fp.writelines(["aa\n","bb\n","cc\n"])
fp.flush()
fp.seek(0,0)
print(fp.read())
結果:
============================= RESTART: E:\aa.py =============================
靜夜思
李白
牀前明月光,
疑是地上霜。
舉頭望明月,
低頭思故鄉。將軍行將軍行aa
bb
cc
>>>
問題1:write函數會清空原來文件中的內容,那麼怎麼才能夠不清除原有內容,再增加新的內容呢?
答案:
1)可以使用“a+”的方式,該種方式在文件末尾增加元素
2)先讀一個文件,將光標移動到最後的位置上,然後再寫入。
注意事項:
序列中的內容也必須是字符串類型的數據,才能夠正常寫入文件。
練習題:寫入一個文件,文件的內容爲:glory1----glory100
# coding=utf-8
'''aa.txt的保存格式爲ansi,也就是默認的gbk類型'''
with open("e:\\cc.txt","w+") as fp:
for i in range(1,101):
fp.write("glory"+str(i)+"\n")
fp.flush()
fp.seek(0,0)
for line in fp:
print(line)
結果:
1.7、文件其他操作
- flush():將緩衝區的內容寫入到硬盤中。其實可以不關閉文件,進行一下刷新機制也是可以的。
- seek(offset,whence):用於移動文件讀取指針的位置,
offset:開始偏移量,也就是代表需要移動偏移的字節數。
whence:可選,默認爲0,0:從文件開頭開始計算。1:從當前位置開始計算。2:從文件末尾開始計算。
- tell():獲取當前文件指針所在的位置。
- close():關閉文件
- truncate([size]):把文件裁定到固定的大小。
1.8、文件的複製(wb,rb)
示例1:複製一個excel表格。
# coding=utf-8
'''複製一個docx文件'''
with open("e:\\python3編程基礎筆記.docx","rb") as fp:
content=fp.read()
fp2=open("e:\\aaaa.docx","wb")
fp2.write(content)
fp2.flush()
fp.close()
結果:
1.9、linecache模塊
注意:
linecache是用utf-8的格式處理文件,所以打開的文件需要utf-8的文件。
- linecache.getlines(filename):從文件中讀取全部內容,輸出爲列表格式,以文件每行爲列表的一個元素,並且以linenum-1爲元素在列表中的存儲位置。
- linecache.checkcache(filename):檢查緩存的有效性。如果在緩存中的文件在硬盤中發生了變化,並且需要你更新版本,使用這個函數,執行此函數會將淘汰的內容刪除。
- linecache.updatecache():更新文件名爲filename的緩存。如果filename文件更新了,使用這個函數可以更新linecache.getlines(filename)返回的列表。如果出錯,則返回空列表。
- linecache.clearcache():清理緩存。
示例:
>>> import linecache
>>> fp=linecache.getlines("e:\\aa.txt")
>>> print(fp)
['君不見\n', '黃河之水\n', '天上開\n', '及低溫\n', 'sdjiwe\n']
>>> fp=linecache.getlines("e:\\aa.txt")[2:]
>>> print(fp)
['天上開\n', '及低溫\n', 'sdjiwe\n']
>>> fp=linecache.updatecache("e:\\aa.txt")
>>> fp=linecache.getline("e:\\aa.txt",2)
>>> print(fp)
黃河之水