【基本的文件操作】 參數: 1、文件路徑; 2、編碼方式; 3、執行動作;(打開方式)只讀,只寫,追加,讀寫,寫讀! ...
一、【基本的文件操作】
參數:
1、文件路徑;
2、編碼方式;
3、執行動作;(打開方式)只讀,只寫,追加,讀寫,寫讀!
#1. 打開文件,得到文件句柄並賦值給一個變數
f = open('E:/Python/file/文件操作測試.txt', encoding='utf-8', mode='r')
content = f.read()
print(content)
f.close()
E:\Python\venv\Scripts\python.exe E:/Python/day08/文件操作.py
文件操作測試讀取,2018-3-27
read
f:變數,f_obj,file,f_handler,...文件句柄。
open --- windows的系統功能,
windows預設編碼方式:gbk,
linux預設編碼方式:utf-8。
f.close() --- 關閉文件(保存退出)
流程:
1、打開一個文件,產生一個文件句柄,
2、通過句柄對文件進行操作,
3、關閉文件。
二、【關閉文件的註意事項】
打開一個文件包含兩部分資源:操作系統級打開的文件+應用程式的變數。
在操作完畢一個文件時,必須把與該文件的這兩部分資源一個不落地回收,回收方法為:
1、f.close() #回收操作系統級打開的文件
2、del f #回收應用程式級的變數
其中del f一定要發生在f.close()之後,
否則就會導致操作系統打開的文件還沒有關閉,白白占用資源,
python自動的垃圾回收機制決定了無需考慮del f,在操作完畢文件後,記住f.close()就可以了。
推薦傻瓜式操作方式:使用with關鍵字來幫我們管理上下文的同時自動關閉文件。
【with】
功能一:自動關閉文件句柄
功能二:一次性操作多個文件句柄
例:
with open('a.txt', encoding='utf-8', 'w') as f:
pass
with open('a.txt', encondig='utf-8', 'w') as read_f,open('b.txt','w') as write_f:
data=read_f.read()
write_f.write(data)
三、【文件的打開模式】
文件句柄 = open(‘文件路徑’,‘模式’)
1、文件以什麼編碼方式存儲的,就以什麼編碼方式打開;
2、文件路徑:
絕對路徑:從根目錄開始
相對路徑:從打開軟體所在的路徑開始(比如pycharm就是在pycharm的工作目錄起)
1. 打開文件的模式有(預設為文本模式):
r, 只讀模式【預設模式,文件必須存在,不存在則拋出異常】
w, 只寫模式【不可讀;文件不存在則創建文件;存在則清空內容】
a, 只追加寫模式【不可讀;文件不存在則創建;存在則只追加內容】
2. 對於非文本文件,(例如圖片)可以使用b模式,"b"表示以位元組的方式操作(而所有文件也都是以位元組的形式存儲的,使用這種模式無需考慮文本文件的字元編碼、圖片文件的jgp格式、視頻文件的avi格式)
rb
wb
ab
具體同上,只是後面加了個b表示是b模式。
註:以b方式打開時,讀取到的內容是位元組類型,寫入時也需要提供位元組類型,不能指定編碼。
3,‘+’模式(就是增加了一個功能)
r+, 讀寫【可讀,可寫】
w+, 寫讀【可寫,可讀】
a+, 追加方式的寫讀【可寫,可讀】
4,以bytes類型操作的讀寫,寫讀,寫讀模式
r+b, 讀寫【可讀,可寫】
w+b, 寫讀【可寫,可讀】
a+b, 追加寫讀【可寫,可讀】
四、【文件操作方式】
【讀模式操作方式】
read()
全部一次性讀取(有缺點:要是一次性讀取超大文件會爆記憶體,例如linux上的日誌文件。)
readline()
每次讀取一行(並且文件內游標隨之移動到第二行頭部)
readlines()
將原文件的每一行作為一個元素放在列表當中(包括\n換行符)可加.strip去掉換行符
read(n)
在r模式下,按字元去讀取n個字元
在rb模式下,按位元組去讀取n個位元組
適合讀取超大文件的方法:
迴圈讀取,全部能讀取出來而且在記憶體當中永遠只占一行。
因為每次都是讀取一行清除一行的記憶體在去讀取下一行。
例:迴圈讀取。
# f = open('log',encoding='utf-8')
# for i in f:
# print(i.strip())
# f.close()
【游標】
文件內游標移動都是以位元組為單位的如:seek,tell,truncate
f.tell() # 按位元組去讀取游標位置
f.seek() # 按位元組調整游標位置
file.seek()方法格式:
seek(offset,whence=0)
移動文件讀取指針(移動游標)到指定位置。
offset:開始的偏移量,也就是代表需要移動偏移的位元組數。
whence(移動模式): 給offset參數一個定義,表示要從哪個位置開始偏移;
0代表從文件開頭算起,
1代表開始從當前位置開始算起,
2代表從文件末尾開始算起。當有換行時,會被換行截斷。
seek的三種移動方式0,1,2,其中1和2必須在b模式下進行,但無論哪種模式,都是以bytes為單位移動的。
seek()無返回值,故值為None
file.truncate():
truncate(),對文字內容進行截取。
truncate是截斷文件,所以文件的打開方式必須可寫,但是不能用w或w+等方式打開,
因為那樣直接清空文件了,所以truncate要在r+或a或a+等模式下測試效果。
【官方源碼參考】
class file(object)
def close(self): # real signature unknown; restored from __doc__
關閉文件
"""
close() -> None or (perhaps) an integer. Close the file.
Sets data attribute .closed to True. A closed file cannot be used for
further I/O operations. close() may be called more than once without
error. Some kinds of file objects (for example, opened by popen())
may return an exit status upon closing.
"""
def fileno(self): # real signature unknown; restored from __doc__
文件描述符
"""
fileno() -> integer "file descriptor".
This is needed for lower-level file interfaces, such os.read().
"""
return 0
def flush(self): # real signature unknown; restored from __doc__
刷新文件內部緩衝區(類似於文件-保存的效果)
""" flush() -> None. Flush the internal I/O buffer. """
pass
def isatty(self): # real signature unknown; restored from __doc__
判斷文件是否是同意tty設備
""" isatty() -> true or false. True if the file is connected to a tty device. """
return False
def next(self): # real signature unknown; restored from __doc__
獲取下一行數據,不存在,則報錯
""" x.next() -> the next value, or raise StopIteration """
pass
def read(self, size=None): # real signature unknown; restored from __doc__
讀取指定位元組數據
"""
read([size]) -> read at most size bytes, returned as a string.
If the size argument is negative or omitted, read until EOF is reached.
Notice that when in non-blocking mode, less data than what was requested
may be returned, even if no size parameter was given.
"""
pass
def readinto(self): # real signature unknown; restored from __doc__
讀取到緩衝區,不要用,將被遺棄
""" readinto() -> Undocumented. Don't use this; it may go away. """
pass
def readline(self, size=None): # real signature unknown; restored from __doc__
僅讀取一行數據
"""
readline([size]) -> next line from the file, as a string.
Retain newline. A non-negative size argument limits the maximum
number of bytes to return (an incomplete line may be returned then).
Return an empty string at EOF.
"""
pass
def readlines(self, size=None): # real signature unknown; restored from __doc__
讀取所有數據,並根據換行保存值到列表
"""
readlines([size]) -> list of strings, each a line from the file.
Call readline() repeatedly and return a list of the lines so read.
The optional size argument, if given, is an approximate bound on the
total number of bytes in the lines returned.
"""
return []
def seek(self, offset, whence=None): # real signature unknown; restored from __doc__
指定文件中指針位置
"""
seek(offset[, whence]) -> None. Move to new file position.
Argument offset is a byte count. Optional argument whence defaults to
(offset from start of file, offset should be >= 0); other values are 1
(move relative to current position, positive or negative), and 2 (move
relative to end of file, usually negative, although many platforms allow
seeking beyond the end of a file). If the file is opened in text mode,
only offsets returned by tell() are legal. Use of other offsets causes
undefined behavior.
Note that not all file objects are seekable.
"""
pass
def tell(self): # real signature unknown; restored from __doc__
獲取當前指針位置
""" tell() -> current file position, an integer (may be a long integer). """
pass
def truncate(self, size=None): # real signature unknown; restored from __doc__
截斷數據,僅保留指定之前數據
"""
truncate([size]) -> None. Truncate the file to at most size bytes.
Size defaults to the current file position, as returned by tell().
"""
pass
def write(self, p_str): # real signature unknown; restored from __doc__
寫內容
"""
write(str) -> None. Write string str to file.
Note that due to buffering, flush() or close() may be needed before
the file on disk reflects the data written.
"""
pass
def writelines(self, sequence_of_strings): # real signature unknown; restored from __doc__
將一個字元串列表寫入文件
"""
writelines(sequence_of_strings) -> None. Write the strings to the file.
Note that newlines are not added. The sequence can be any iterable object
producing strings. This is equivalent to calling write() for each string.
"""
pass
def xreadlines(self): # real signature unknown; restored from __doc__
可用於逐行讀取文件,非全部
"""
xreadlines() -> returns self.
For backward compatibility. File objects now include the performance
optimizations previously implemented in the xreadlines module.
"""
pass
五、【文件的修改】
文件的數據是存放於硬碟上的,因而實際上底層只存在覆蓋、不存在修改這麼一說,
我們平時看到的修改編輯文件,都是模擬出來的效果,具體的說有兩種實現方式:
方式一:將硬碟存放的該文件的內容全部載入到記憶體,在記憶體中是可以修改的,修改完畢後,再由記憶體覆蓋到硬碟(word,vim,nodpad++等編輯器)
---------------------------
import os # 調用系統模塊
with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
data=read_f.read() #全部讀入記憶體,如果文件很大,會很卡
data=data.replace('old','new') #在記憶體中完成修改,將舊內容替換成新內容
write_f.write(data) #一次性寫入新文件
os.remove('a.txt') #刪除原文件
# 因為不刪除將建立不了同名的文件,其實我感覺上先將原文件改名再讓新文件命名成原文件名後確認無誤後再刪除原文件更安全保險。
os.rename('.a.txt.swap','a.txt') #將新建的文件重命名為原文件
-----------------------------
方式二:將硬碟存放的該文件的內容一行一行地讀入記憶體,修改完畢就寫入新文件,最後用新文件覆蓋源文件。
import os
with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
for line in read_f:
line=line.replace('old','new')
write_f.write(line)
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')
簡述為以下流程:
1、將源文件讀取到記憶體;
2、在記憶體中時行修改,形成新的字元串(文件);
3、將新的字元串寫入新文件;
3、將原文件刪除;
4、將新文件重命名為原文件。
例:有如下文件:
-------
alex是老男孩python發起人,創建人。
alex其實是人妖。
誰說alex是sb?
你們真逗,alex再牛逼,也掩飾不住資深屌絲的氣質。
----------
將文件中所有的alex都替換成大寫的SB。
答:
with open('log',encoding='utf-8') as f1,\
open('log.bak',encoding='utf-8',mode='w') as f2:
content = f1.read()
new_content = content.replace('alex','SB')
f2.write(new_content)
os.remove('log')
os.rename('log.bak','log')
import os
with open('log',encoding='utf-8') as f1,\
open('log.bak',encoding='utf-8',mode='w') as f2:
for i in f1:
new_i = i.replace('SB','alex')
f2.write(new_i)
os.remove('log')
os.rename('log.bak','log')
end
2018-4-2