【目錄】
1、什么是檔案
2、為何要用檔案
3、如何使用檔案
3.1 基本操作流程
3.1.1 基本流程
3.1.2 with背景關系管理
3.1.3 指定字符編碼
3.2 模式介紹
3.3 檔案的操作模式
3.3.1 控制檔案讀寫內容的模式
3.3.2 控制檔案讀寫操作的模式
3.4 操作檔案的其他方法
3.5主動控制檔案內指標移動
3.6檔案的修改
1、什么是檔案
檔案是作業系統提供給用戶/應用程式操作硬碟的一種虛擬的概念/介面
==計算機三大層次結構==
用戶/應用程式(open())
作業系統(檔案)
計算機硬體(硬碟)
2、為何要用檔案
==保存資料==
用戶/應用程式 可以通過檔案將資料永久保存的硬碟中 ,即操作檔案就是操作硬碟
==讀取資料==
用戶/應用程式 直接操作的是檔案,對檔案進行的所有的操作,都是在向作業系統發送系統呼叫,然后再由操作將其轉換成具體的硬碟操作
3、如何使用檔案
3.1 基本操作流程
3.1.1 基本流程
=1=打開檔案——檔案句柄 :open('檔案路徑', '模式')
=Windows路徑分隔符問題
open('C:\a.txt\nb\c\d.txt') # 解決方案一:推薦(windows系統的路徑是用 \ 間隔) open(r'C:\a.txt\nb\c\d.txt') # 解決方案二:(Linux系統的路徑是用 / 間隔) open('C:/a.txt/nb/c/d.txt')
f=open(r'aaa/a.txt',mode='rt') # f的值是一種變數,占用的是應用程式的記憶體空間.
r 的作用是避免路徑中出現的‘\n’被解釋器識別為轉義字符 # print(f) # x=int(10)
f=open('a.txt','r')的程序分析
#1、由應用程式向作業系統發起系統呼叫open(...)
#2、作業系統打開該檔案,并回傳一個檔案句柄給應用程式
#3、應用程式將檔案句柄賦值給變數f
=絕對路徑和相對路徑
https://www.cnblogs.com/bigorangecc/p/11179863.html
=2=操作檔案:讀/寫檔案—— res=f.read() res=f.write()
讀/寫檔案,應用程式對檔案的讀寫請求都是在向作業系統發送系統呼叫,然后由作業系統控制硬碟把輸入讀入記憶體、或者寫入硬碟
res=f.read() print(type(res)) # print(res)
=3=關閉檔案 —— f.close()
f.close() # 回收作業系統資源print(f)f.read() # 變數f存在,但是不能再讀了del f # 回收應用程式資源
3.1.2 with背景關系管理
=1= 作用一:為了防止遺漏 f.close()
# 檔案物件又稱為檔案句柄 # with open('a.txt',mode='rt') as f1: # f1=open('a.txt',mode='rt') # res=f1.read() # print(res)
=2= 作用二:一次讀取多個檔案
with open('a.txt',mode='rt') as f1,\ # 一次輸入有換行的代碼—— \的作用是反義字符,本身換行了,再在文末加上反義字符 \,則表示上下兩行是同一部分的內容 open('b.txt',mode='rt') as f2: res1=f1.read() res2=f2.read() print(res1) print(res2) # f1.close() # f2.close()
3.1.3 指定字符編碼
強調:t 和 b不能單獨使用,必須跟r/w/a連用
t文本(默認的模式)
1、讀寫都以str(unicode)為單位的
2、文本檔案
3、必須指定encoding='utf-8'
# 沒有指定encoding引數作業系統會使用自己默認的編碼 # linux系統默認utf-8 # windows系統默認gbk with open('c.txt',mode='rt',encoding='utf-8') as f: res=f.read() # t模式會將f.read()讀出的結果解碼成unicode print(res,type(res)) # 記憶體:utf-8格式的二進制-----解碼-----》unicode # 硬碟(c.txt內容:utf-8格式的二進制)
3.2 模式介紹
=1= 模式一:控制檔案讀寫內容的模式—— t 和 b
強調:t 和 b 不能單獨使用,必須跟r / w / a 連用
t 模式
1、讀寫都是以字串(unicode)為單位
2、只能針對文本檔案
3、必須指定字符編碼,即必須指定encoding引數
b 模式(binary模式)
1、讀寫都是以位元組bytes為單位
2、可以針對所有檔案
3、一定不能指定字符編碼,即一定不能指定encoding引數
總結:
1、在操作純文本檔案方面,t 模式幫我們省去了編碼與解碼的環節,b 模式則需要手動編碼與解碼,所以此時 t 模式 更為方便
2、針對非文本檔案(如圖片、視頻、音頻等)只能使用b模式
=2= 模式二:控制文本讀寫操作的模式—— r /w / a / +
r—只讀模式
w—只寫模式
a—只追加寫模式
+—r+、w+、a+
x—只寫模式
3.3 檔案的操作模式
3.3.1 控制檔案讀寫內容的模式
1、t 模式
t模式只能讀文本檔案
# 錯誤演示:t模式只能讀文本檔案 with open(r'愛情公寓.mp4',mode='rt') as f: f.read() # 硬碟的二進制讀入記憶體-》t模式會將讀入記憶體的內容進行decode解碼操作
with open(r'd.txt',mode='rt',encoding='utf-8') as f: res=f.read() # utf-8的二進制->unicode print(res)
2、b 模式
2.1 讀取圖片
with open(r'test.jpg',mode='rb',encoding='utf-8') as f: res=f.read() # 硬碟的二進制讀入記憶體—>b模式下,不做任何轉換,直接讀入記憶體 print(res) # bytes型別—》當成二進制 print(type(res))
2.2 讀取文本檔案
with open(r'd.txt',mode='rb') as f: res=f.read() # utf-8的二進制 print(res,type(res)) print(res.decode('utf-8'))
2.3 b模式下寫入檔案
with open(r'f.txt',mode='wb') as f: f.write('你好hello'.encode('utf-8')) f.write('哈哈哈'.encode('gbk'))
2.4 案例——改寫檔案copy工具
# 檔案拷貝工具 src_file=input('源檔案路徑>>: ').strip() dst_file=input('源檔案路徑>>: ').strip() with open(r'{}'.format(src_file),mode='rb') as f1,\ open(r'{}'.format(dst_file),mode='wb') as f2: # res=f1.read() # 記憶體占用過大 # f2.write(res) for line in f1: #推薦使用 f2.write(line)
3、案例分析——r、b對比—回圈讀取檔案
方式一:自己控制每次讀取的資料的資料量 with open(r'test.jpg',mode='rb') as f: while True: res=f.read(1024) # 1024 if len(res) == 0: break print(len(res)) 方式二:以行為單位讀,當一行內容過長時會導致一次性讀入內容的資料量過大 with open(r'g.txt',mode='rt',encoding='utf-8') as f: for line in f: print(len(line),line) with open(r'g.txt',mode='rb') as f: for line in f: print(line) with open(r'test.jpg',mode='rb') as f: for line in f: print(line)
3.3.2 控制檔案讀寫操作的模式——以 t 模式為基礎進行記憶體操作
1、r(默認的操作模式):只讀模式,當檔案不存在時報錯,當檔案存在時檔案指標跳到開始位置
with open('c.txt',mode='rt',encoding='utf-8') as f: print('第一次讀'.center(50,'*')) res=f.read() # 把所有內容從硬碟讀入記憶體 print(res) with open('c.txt', mode='rt', encoding='utf-8') as f: print('第二次讀'.center(50,'*')) res1=f.read() print(res1)
案例一 :用戶登入驗證
用戶登入驗證:
inp_username=input('your name>>: ').strip() inp_password=input('your password>>: ').strip() # 驗證 with open('user.txt',mode='rt',encoding='utf-8') as f: for line in f: # print(line,end='') # egon:123\n username,password=line.strip().split(':') if inp_username == username and inp_password == password: print('login successfull') break else: print('賬號或密碼錯誤')
2、w:只寫模式,當檔案不存在時會創建空檔案,當檔案存在會清空檔案,指標位于開始位置
with open('d.txt',mode='wt',encoding='utf-8') as f: f.read() # 報錯,不可讀 f.write('擦勒\n') 強調1: 在以w模式打開檔案沒有關閉的情況下,連續寫入,新的內容總是跟在舊的之后
with open('d.txt',mode='wt',encoding='utf-8') as f: f.write('你好1\n') f.write('你好2\n') f.write('你好3\n') 強調2: 如果重新以w模式打開檔案,則會清空檔案內容 with open('d.txt',mode='wt',encoding='utf-8') as f: f.write('你好1\n') with open('d.txt',mode='wt',encoding='utf-8') as f: f.write('你好2\n') with open('d.txt',mode='wt',encoding='utf-8') as f: f.write('你好3\n')
案例二 :w模式用來創建全新的檔案——文本檔案的copy工具
文本檔案的copy工具
src_file=input('源檔案路徑>>: ').strip() dst_file=input('源檔案路徑>>: ').strip() with open(r'{}'.format(src_file),mode='rt',encoding='utf-8') as f1,\ open(r'{}'.format(dst_file),mode='wt',encoding='utf-8') as f2: res=f1.read() f2.write(res)
3、a:只追加寫,在檔案不存在時會創建空檔案,在檔案存在時檔案指標會直接調到末尾
with open('e.txt',mode='at',encoding='utf-8') as f: # f.read() # 報錯,不能讀 f.write('擦嘞1\n') f.write('擦嘞2\n') f.write('擦嘞3\n') 強調 w 模式與 a 模式的異同: 1 相同點:在打開的檔案不關閉的情況下,連續的寫入,新寫的內容總會跟在前寫的內容之后 2 不同點:以 a 模式重新打開檔案,不會清空原檔案內容,會將檔案指標直接移動到檔案末尾,新寫的內容永遠寫在最后
案例三:a模式用來在原有的檔案記憶體的基礎之上寫入新的內容,比如記錄日志、注冊
注冊功能 name=input('your name>>: ') pwd=input('your code>>: ') with open('db.txt',mode='at',encoding='utf-8') as f: f.write('{}:{}\n'.format(name,pwd))
4、了解:
+不能單獨使用,必須配合r、w、a
with open('g.txt',mode='r+t',encoding='utf-8') as f: # print(f.read()) f.write('中國') with open('g.txt',mode='w+t',encoding='utf-8') as f: f.write('111\n') f.write('222\n') f.write('333\n') print('====>',f.read()) with open('g.txt',mode='a+t',encoding='utf-8') as f: print(f.read()) f.write('444\n') f.write('5555\n') print(f.read())
x,只寫模式【不可讀;不存在則創建,存在則報錯】,x+【寫讀--可讀,可寫】,xb
with open('a.txt',mode='x',encoding='utf-8') as f: pass with open('c.txt',mode='x',encoding='utf-8') as f: f.read() with open('d.txt',mode='x',encoding='utf-8') as f: f.write('哈哈哈\n')
3.4 檔案操作的其他方法
=1= 讀相關操作
f.read() # 讀取所有內容,執行完該操作后,檔案指標會移動到檔案末尾
f.readline() # 讀取一行內容,游標移動到第二行首部
f.readlines() # 讀取每一行內容,存放于串列中
=1、readline() —— 一次讀一行
with open(r'g.txt',mode='rt',encoding='utf-8') as f: # res2=f.readline() # print(res2) while True: #也可以用while實作 line=f.readline() if len(line) == 0: break print(line)
=2、readlines()
with open(r'g.txt',mode='rt',encoding='utf-8') as f: res=f.readlines() print(res)
# 強調:
f.read() 與 f.readlines()都是將內容一次性讀入記憶體,如果內容過大會導致記憶體溢位,若還想將內容全讀入記憶體,則必須分多次讀入,有兩種實作方式:
(同-回圈讀取檔案)
# 方式一 with open('a.txt',mode='rt',encoding='utf-8') as f: for line in f: print(line) # 同一時刻只讀入一行內容到記憶體中 # 方式二 with open('1.mp4',mode='rb') as f: while True: data=f.read(1024) # 同一時刻只讀入1024個Bytes到記憶體中 if len(data) == 0: break print(data)
=2= 寫相關操作
f.write('1111\n222\n') # 針對文本模式的寫,需要自己寫換行符
f.write('1111\n222\n'.encode('utf-8')) # 針對b模式的寫,需要自己寫換行符,且指定編碼格式
f.writelines(['333\n','444\n']) # 檔案模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
=1、f.writelines():
with open('h.txt',mode='wt',encoding='utf-8') as f: # f.write('1111\n222\n3333\n') # l=['11111\n','2222','3333',4444] l=['11111\n','2222','3333'] # for line in l: # f.write(line) f.writelines(l)
with open('h.txt', mode='wb') as f: # l = [ # '1111aaa1\n'.encode('utf-8'), # '222bb2'.encode('utf-8'), # '33eee33'.encode('utf-8') # ] # 補充1:如果是純英文字符,可以直接加前綴b得到bytes型別 # l = [ # b'1111aaa1\n', # b'222bb2', # b'33eee33' # ] # 補充2:'上'.encode('utf-8') 等同于bytes('上',encoding='utf-8') l = [ bytes('上啊',encoding='utf-8'), bytes('沖呀',encoding='utf-8'), bytes('小超人們',encoding='utf-8'), ] f.writelines(l)
=2、 flush() ,強制寫入資料
with open('h.txt', mode='wt',encoding='utf-8') as f: f.write('哈') # f.flush()
=3、了解
f.readable() # 檔案是否可讀
f.writable() # 檔案是否可寫
f.closed # 檔案是否關閉
f.encoding # 如果檔案打開模式為b,則沒有該屬性
f.flush() # 立刻將檔案內容從記憶體刷到硬碟,即強制寫入硬碟
f.name
with open('h.txt', mode='wt',encoding='utf-8') as f: print(f.readable()) print(f.writable()) print(f.encoding) print(f.name) print(f.closed)
3.5 主動控制檔案內指標移動
=1= 指標移動的單位都是以bytes/位元組為單位,
只有一種情況特殊:
t 模式下的read(n), n代表的是字符個數
with open('a.txt',mode='rt',encoding='utf-8') as f: data=f.read(3) # 讀取3個字符 with open('a.txt',mode='rb') as f: data=f.read(3) # 讀取3個Bytes
=2= f.seek(指標移動的位元組數,模式控制)
# 之前檔案內指標的移動都是由 讀/寫操作 而被動觸發的,
若想讀取檔案某一特定位置的資料,則需要用f.seek()方法 主動控制檔案內指標的移動,
詳細用法如下:
# f.seek(指標移動的位元組數,模式控制):
# 模式控制:
# 0: 默認的模式,該模式代表指標移動的位元組數是以檔案開頭為參照的
# 1: 該模式代表指標移動的位元組數是以當前所在的位置為參照的
# 2: 該模式代表指標移動的位元組數是以檔案末尾的位置為參照的
# 強調:其中0模式可以在t模式或者b模式使用,而1跟2模式只能在b模式下用
模式: 0模式:參照物是檔案開頭位置 f.seek(9,0) f.seek(3,0) # 指標停在索引3的位置 1模式:參照物是當前指標所在位置 f.seek(9,1) f.seek(3,1) # 12 2模式:參照物是檔案末尾位置,應該倒著移動 f.seek(-9,2) # 3 f.seek(-3,2) # 9
=3= f.tell() # 獲取檔案指標當前位置
示范 with open('aaa.txt',mode='rb') as f: f.seek(9,0) f.seek(3,0) # 3 # print(f.tell()) f.seek(4,0) res=f.read() print(res.decode('utf-8')) with open('aaa.txt',mode='rb') as f: f.seek(9,1) f.seek(3,1) # 12 print(f.tell()) with open('aaa.txt',mode='rb') as f: f.seek(-9,2) # print(f.tell()) f.seek(-3,2) # print(f.tell()) print(f.read().decode('utf-8'))
3.6 檔案的修改
# 檔案a.txt內容如下 張一蛋 山東 179 49 12344234523 李二蛋 河北 163 57 13913453521 王全蛋 山西 153 62 18651433422 # 執行操作 with open('a.txt',mode='r+t',encoding='utf-8') as f: f.seek(9) f.write('<婦女主任>') # 檔案修改后的內容如下 張一蛋<婦女主任> 179 49 12344234523 李二蛋 河北 163 57 13913453521 王全蛋 山西 153 62 18651433422 # 強調: # 1、硬碟空間是無法修改的,硬碟中資料的更新都是用新內容覆寫舊內容 # 2、記憶體中的資料是可以修改的
檔案對應的是硬碟空間,硬碟不能修改對應著檔案本質也不能修改, 那我們看到檔案的內容可以修改,是如何實作的呢?
大致的思路是: 將硬碟中檔案內容讀入記憶體,然后在記憶體中修改完畢后再覆寫回硬碟
具體的實作方式分為兩種:
=1= 檔案修改方式一
# 實作思路:將檔案內容發一次性全部讀入記憶體,然后在記憶體中修改完畢后再覆寫寫回原檔案
# 優點: 在檔案修改程序中同一份資料只有一份
# 缺點: 會過多地占用記憶體一般是文本編輯器使用的檔案修改方式
with open('db.txt',mode='rt',encoding='utf-8') as f: data=f.read() with open('db.txt',mode='wt',encoding='utf-8') as f: f.write(data.replace('kevin','SB'))
=2= 檔案修改方式二
# 實作思路:以讀的方式打開原檔案,以寫的方式打開一個臨時檔案,一行行讀取原檔案內容,修改完后寫入臨時檔案...,
刪掉原檔案,將臨時檔案重命名原檔案名
# 優點: 不會占用過多的記憶體
# 缺點: 在檔案修改程序中同一份資料存了兩份多用于程式里的檔案修改
import os with open('db.txt',mode='rt',encoding='utf-8') as read_f,\ open('.db.txt.swap',mode='wt',encoding='utf-8') as wrife_f: #.db.txt.swap 是Linux系統的命名規則,‘.’開頭是隱藏檔案 for line in read_f: wrife_f.write(line.replace('SB','kevin')) os.remove('db.txt') # 洗掉原檔案 os.rename('.db.txt.swap','db.txt') #將新檔案重命名為原檔案名
參考資料:
https://www.cnblogs.com/linhaifeng/articles/5984922.html
https://zhuanlan.zhihu.com/p/108808704
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/177777.html
標籤:Python
上一篇:Python的主要功能是什么?
