python的文件操作


python的文件操作image

1、什么是文件
    文件是操作提供給用戶/應用程序存取硬盤的一種機制

2、為何要用文件
    永久保存數據

3、代碼如何操作文件
	關鍵字open()
    三步走:
    	1.利用關鍵字open打開文件
        2.利用其它方法操作文件
        3.關閉文件

文件路徑image

相對路徑與絕對路徑
所謂相對路徑,就是相對於自己的目標文件位置。

相對路徑:
image
絕對路徑:
image

路徑中出現了字母與斜杠的組合產生了特殊含義如何取消?
在路徑字符串前面加一個r
r'D:\pycharm\測試\a.txt'
image

其中如果打開一個文件,需要這三個參數:image

image
open(文件路徑,讀寫模式,字符編碼)
文件路徑與讀寫模式是必須的
字符編碼是可選的(有些模式需要編碼)
res = open('a.txt', 'r', encoding='utf8')
文件運行的流程是這樣的。
image
打開文件,由應用程序向操作系統發起系統調用open(...),操作系統打開該文件,對應一塊硬盤空間,並返回一個文件對象賦值給一個變量 res
image

print(res.read()) 調用文件對象下的讀/寫方法,會被操作系統轉換為讀/寫硬盤的操作

res.close() 向操作系統發起關閉文件的請求,回收系統資源

打開一個文件包含兩部分資源:
應用程序的變量res和操作系統打開的文件。在操作完畢一個文件時,必須把與該文件的這兩部分資源全部回收
,回收方法為:image

1、res.close() #回收操作系統打開的文件資源
2、del res #回收應用程序級的變量

其中 del res一定要發生在res.close()之后,否則就會導致操作系統打開的文件無法關閉,白白占用資源。
而python自動的垃圾回收機制決定了我們無需考慮del res,這就要求我們,在操作完畢文件后,一定要記住res.close(),但是大多數人還是會不由自主的忘記res.close,考慮到這一點,python提供了關鍵字with

1、在執行完子代碼塊后,with 會自動執行f.close()image

with open('a.txt','w') as res:
pass
image
其中,pass只是為了補全語法結構,沒有實際意義。

2、可用用with同時打開多個文件,用逗號分隔開即可image

with open('a.txt','r') as read_res,open('b.txt','w') as write_res:
data = read_res.read()
write_res.write(data)

指定操作文本文件的字符編碼image

f = open(...)是由操作系統打開文件,如果打開的是文本文件,會涉及到字符編碼問題,如果沒有為open指定編碼,那么打開文本文件的默認編碼很明顯是操作系統說了算了,操作系統會用自己的默認編碼去打開文件,在windows下是gbk,在linux下是utf-8。

這就用到了上節課講的字符編碼的知識:若要保證不亂碼,文件以什么方式存的,就要以什么方式打開。

f = open('a.txt','r',encoding='utf-8')

控制文件讀寫操作的模式

只需要記住3個①. 'r'(默認的):只讀 ②.'w':只寫 ③.'a':只追加寫
r 只讀模式(只能看不能改)

# 路徑不存在:直接報錯
 with open(r'b.txt', 'r', encoding='utf8') as f:
     pass
# 路徑存在
 with open(r'a.txt', 'r', encoding='utf8') as f:
     print(f.read())  # 讀取文件內所有的內容
     f.write('123')  # 寫文件內容

image

w 只寫模式(只能寫不能看)image

# 路徑不存在:自動創建
# with open(r'b.txt', 'w', encoding='utf8') as f:
#     pass

# 路徑存在:1.會先清空文件內容  2.再執行寫入操作
with open(r'a.txt', 'w', encoding='utf8') as f:
    # f.read()
    f.write('hello world!\n')
    f.write('hello world!\n')
    f.write('hello world!\n')

運行之前image
運行
image
運行之后直接被清空重新寫入hello world!image

image

a 只追加模式(追加內容)image

#路徑不存在:自動創建
# a模式  只追加模式
with open(r'a.txt','a',encoding='utf8') as f:
 pass
路徑存在:不會清空文件 在文件末尾添加內容
with open(r'a.txt', 'a', encoding='utf8') as f:
 f.write('\n今天周四了 馬上又要放假了 好開心!')

image
運行五次之后image
小總結
我們所使用的r w a讀寫模式都只能操作文本文件

文件操作方法image

# 文件操作方法
# 1.讀系列
with open(r'a.txt', 'r', encoding='utf8') as f:
    # print(f.read())  # 一次性讀取文件內所有的內容
    # print(f.readline())  # 每次只讀文件一行內容
    # print(f.readlines())  # 讀取文件所有的內容 組織成列表 每個元素是文件的每行內容
    # print(f.readable())  # 判斷當前文件是否具備讀的能力


# 2.寫系列
with open(r'a.txt','w',encoding='utf8') as f:
    # f.write('克服一切困難 奧利給!')  # 往文件內寫入文本內容
    # f.write(123)  # 寫入的內容必須是字符串類型
    # f.writelines(['jason','kevin','tony'])  # 可以將列表中多個字符串元素全部寫入
    # print(f.writable())  # True
    # print(f.readable())  # False
    f.flush()  # 直接將內存內文件數據刷到硬盤 相當於ctrl+s

文件優化操作image

with open(r'a.txt', 'r', encoding='utf8') as f:
    # print(f.read())  # 一次性讀取文件內所有的內容
    # print(f.read())  # 一次性讀取文件內所有的內容
    # print(f.read())  # 一次性讀取文件內所有的內容
    """
    1.一次性讀完之后 光標停留在了文件末尾 無法再次讀取內容
    2.該方法在讀取大文件的時候 可能會造成內存溢出的情況
        解決上述問題的策略就是逐行讀取文件內容
    """
    # for line in f:  # 文件變量名f支持for循環  相當於一行行讀取文件內容
    #     line
    '''以后涉及到多行文件內容的情況一般都是采用for循環讀取'''

簡易版本的拷貝功能
1.獲取待拷貝的目標文件路徑
2.獲取即將拷貝到哪個地方的新路徑
3.利用文件操作實現數據拷貝

**1.待拷貝的文件路徑**
wait_copy_file = input('file path>>>:').strip()
**2.新的文件路徑**
new_file_path = input('new path>>>:').strip()
**3.以r模式打開步驟1的路徑 以w模式打開步驟2的路徑**
		with open(r'%s' % wait_copy_file, 'rb') as f1, \
			open(r'%s' % new_file_path, 'wb') as f2:
		for line in f1:
			f2.write(line)

二進制模式讀寫操作image

with open(r'a.txt','rb') as f:
# print(f.read())
print(f.read(6).decode('utf8')) #b模式下表示字節個數

with open(r'a.txt','r',encoding='utf8') as f:
print(f.read())
print(f.read(4)) 默認的t模式下表示字符個數

"""
read()  括號內可以放數字
	在t模式下表示字符個數
	在b模式下表示字節個數
英文字符統一使用一個bytes來表示
中文字符統一使用三個bytes來表示
"""


# with open(r'b.txt', 'rb') as f:
#     print(f.read(4).decode('utf8'))
#     print(f.tell()) 
# 查看光標移動了多少個字節
#     f.seek(3, 1)
#     print(f.read().decode('utf8'))
"""
控制文件內光標的移動  f.seek()
f.seek(offset,whence)
	offset表示位移量
		始終是以字節為最小單位
			正數從左往右移動
			負數從右往左移動
	whence表示模式
		0:以文件開頭為參考系(支持tb兩種模式)
		1:只支持b模式 以當前位置為參考系
		2:只支持b模式 以文件末尾為參考系
"""

# with open(r'b.txt', 'rb') as f:
#     print(f.read(4).decode('utf8'))
#     print(f.tell())  # 查看光標移動了多少個字節
#     f.seek(3, 1)
#     print(f.read().decode('utf8'))
"""
控制文件內光標的移動  f.seek()
f.seek(offset,whence)
	offset表示位移量
		始終是以字節為最小單位
			正數從左往右移動
			負數從右往左移動
	whence表示模式
		0:以文件開頭為參考系(支持tb兩種模式)
		1:只支持b模式 以當前位置為參考系
		2:只支持b模式 以文件末尾為參考系
"""

小練習:實現動態查看最新一條日志的效果
image

import time
with open('a.txt', 'rb') as f:
	f.seek(0, 2)
	while True:
		line = f.readline()
		if len(line) == 0:
			# 沒有內容
			time.sleep(0.5)
		else:
			print(line.decode('utf-8'), end='')
import time
with open('a.txt', 'rb') as f:
	f.seek(0, 2)
	while True:
		line = f.readline()
		if len(line) == 0:
			# 沒有內容
			time.sleep(0.5)
		else:
			print(line.decode('utf-8'), end='')

文件的內容修改image

# 第一種方法(廢內存)
with open('a.txt', 'r', encoding='utf8') as f:  # 打開一個文本文件a.txt選擇只讀模式
	res = f.read()  # 將讀出來的文件賦值給res,讀取到內存空間。
	data = res.replace('lin', 'xxx')  # 然后再把res里面的內容修改后交給變量名data
with open('a.txt', 'w', encoding='utf8') as f1:  # 再將a.txt文件內容清空,重新寫入data里的內容~
	f1.write(data)
# 這種方法如果要修改的文本文件大的話,對內存占用大。


# 第二種方法  導入標准庫os,遍歷寫入(節省內存,損耗硬盤)
import os  # 導入標准庫os

# 然后打開要修改的a.txt選擇只讀賦值給f,打開並創建一個a.txt.swap的文件(可以理解為虛擬文件),賦值給f1
with open('a.txt', 'r', encoding='utf8') as f, \
		open('.a.txt.swap', 'w', encoding='utf8') as f1:
	for line in f:  # 遍歷獲取a.txt每一行內容
		f1.write(line.replace('lin', 'xxx'))  # 將其中關於lin的內容修改為xxx
os.remove('a.txt')  # 隨后先刪除掉舊得a.txt   並將創建的.a.txt.swap文件名改為 a.txt
os.rename('.a.txt.swap', 'a.txt')

兩種方法視情況使用,如果文件過大使用第二種方法,反之,使用第一種更方便~image

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM