05 python開發之檔案處理
5 檔案處理
5.1 字元編碼
5.1.1 基本概念
-
字元編碼
文字元號-----------------編碼----------------->數字
文字元號<----------------編碼------------------數字
-
字元編碼表:一個字元對應一個數字
-
研究字元編碼表是為了解決亂碼問題
存取都用同一張字元編碼表
-
儲備知識:CPU、記憶體、硬碟
-
執行python程式的三個階段
Ⅰ 先啟動一個python直譯器
Ⅱ python直譯器會將檔案內容從硬碟讀入記憶體
Ⅲ python直譯器會解釋執行剛剛讀入記憶體的程式碼,識別語法
x = "你好Hello"
5.1.2 發展歷程
-
一家獨大
ASCⅡ:只能識別英文字元,用8個bit對應一個英文字元
-
天下大亂
GBK:能識別中文和英文,用16個bit(2Bytes)對應一個字元
shift-JIS
Euc-KR
-
歸於統一
unicode:能識別萬國字元,常用16bit(2Bytes)對應一個字元
5.1.3 使用
- part1
英文字元------->記憶體(ASCⅡ格式的二進位制數)---->硬碟(ASCⅡ格式的二進位制數)
中文、英文字元------->記憶體(GBK格式的二進位制數)----->硬碟(GBK格式的二進位制數)
日文、英文字元--->記憶體(shift-JIS格式的二進位制數)--->硬碟(shift-JIS格式的二進位制數)
萬國字元----->記憶體(Unicode格式的二進位制數)---->硬碟(utf-8格式的二進位制數)
- part2
字元-------->unicode格式的二進位制(記憶體)---------------->utf-8格式的二進位制(硬碟)
編碼 編碼
字元<--------unicode格式的二進位制(記憶體)<----------------utf-8格式的二進位制(硬碟)
解碼 解碼
x = "上"
print(x) # 列印unicode相當於列印字元
utf8_res = x.encode("utf-8")
# print(utf8_res, type(utf8_res)) # b'\xe4\xb8\x8a' <class 'bytes'>
unicode_res = utf8_res.decode("utf-8")
print(unicode_res)
5.2 檔案處理基礎
5.2.1 基本概念
-
檔案是作業系統提供給使用者/應用程式存取硬碟的一種機制
-
檔案可以永久儲存資料
-
如何使用檔案
應用程式 open()
作業系統 檔案
計算機硬體(硬碟)
5.2.2 操作檔案的步驟
-
rawstring原生路徑
f = open(r'檔案絕對路徑/相對路徑')
f的值,檔案物件/檔案控制程式碼
-
data = f.read()
print(data)
-
f.close() # 回收系統資源
5.2.3 with上下文管理
with open(r'絕對路徑或相對路徑') as f1,\
open(r'絕對路徑或相對路徑') as f2:
f1.read()
f2.read()
with open(r'第二週計劃', "rt", encoding='utf-8') as f1:
data = f1.read()
print(data)
f1.close()
data = f1.read()
print(data)
5.3 檔案開啟模式
5.3.1 控制讀寫操作模式
- r : 只讀(預設)
- w : 只寫
- a : 只追加寫
5.3.2 控制讀寫內容的模式
- t : 讀寫都是文字格式,即讀寫都是用字串(預設)
- b : 讀寫都是bytes格式,bytes等同於二進位制
強調:如果是t模式,一定要加上encoding="編碼格式"
如果是b模式,一定不可以加上encoding="編碼格式"
5.3.3 常規使用
- r:在檔案存在的時候,檔案指標調到檔案的開頭,檔案不存在直接報錯
r:在檔案存在的時候,檔案指標調到檔案的開頭,檔案不存在直接報錯
f = open("a.txt", mode="rt", encoding="utf-8")
res = f.read()
print(res)
f.close()
- w:在檔案存在的時候會清空檔案,指標調到檔案開頭,檔案不存在會建立空新檔案
w:在檔案存在的時候會清空檔案,指標調到檔案開頭,檔案不存在會建立空新檔案
f = open("a.txt", mode="wt", encoding="utf-8")
f.write("你好\n666")
f.close()
- a:在檔案存在的時候不會清空檔案,指標跳到檔案末尾,檔案不存在會建立空新檔案
a:在檔案存在的時候不會清空檔案,指標跳到檔案末尾,檔案不存在會建立空新檔案
f = open("a.txt", mode="at", encoding="utf-8")
f.write("\n777")
f.close()
- rb wb ab
rb wb ab
f = open("a.txt", mode="rb")
res = f.read()
print(res)
print(res.decode("utf-8"))
f.close()
f = open("a.txt", mode="wb")
f.write("你好".encode('utf-8'))
f.close()
- 圖片、視訊等非文字檔案只能用b模式
with open(r'H:\BaiduNetdiskDownload\Linux階段總結\img\day004主機板.png', mode='rb') as f1,\
open(r'C:\Users\曹嘉鑫\Desktop\1111.png', mode='wb') as f2:
# res = f1.read()
# f2.write(res)
for line in f1:
f2.write(line)
5.3.4 擴充功能
with open('a.txt', mode='r+t', encoding='utf-8') as f:
print(f.read())
print(f.writable())
print(f.readable())
f.write("你好")
with open('a.txt', mode='w+t', encoding='utf-8') as f:
print(f.writable())
print(f.readable())
f.write("你好")
res = f.read()
print("===> %s" % res)
with open('a.txt', mode='a+t', encoding='utf-8') as f:
print(f.writable())
print(f.readable())
print(f.read())
f.flush()
print(f.name)
print(f.encoding)
5.4 檔案處理的其他辦法
5.4.1 讀操作
with open('a.txt', mode='rt', encoding='utf-8') as f:
line1 = f.readline()
print(line1)
line2 = f.readline()
print(line2)
for line in f:
print(line)
lines = f.readlines()
print(lines)
5.4.2 寫操作
with open('a.txt', mode='wt', encoding='utf-8') as f:
f.write("1111\n2222\n3333\n")
for x in "hello":
f.write(x)
f.writelines("hello") # f.write("hello")
f.writelines(["111", "222", "333"])
f.writelines(["111\n", "222\n", "333\n"])
5.5 控制指標移動
5.5.1 重要概念
- 檔案內指標移動,除了t模式下的read(n)中n代表的是字元個數
- 其他都是以bytes為單位的
with open('a.txt', mode='rt', encoding='utf-8') as f:
res = f.read(6)
print(res)
with open('a.txt', mode='rb') as f:
res = f.read(8)
print(res)
print(res.decode('utf-8'))
with open('a.txt', mode='r+', encoding='utf-8') as f:
f.truncate(8)
5.5.2 f.seek()
-
f.seek(移動的位元組個數,模式)
-
三種模式
0 : 參照檔案開頭移動指標
1 : 參照當前所在的位置移動指標
2 : 參照檔案末尾位置移動指標
-
只有0模式可以在t下使用
-
1和2只能在b下使用
只有0模式可以在t下使用,1和2只能在b下使用
with open('a.txt', mode='a+b') as f:
print(f.tell()) # 檢視指標在檔案的第幾個位元組
with open('a.txt', mode='r+b') as f:
f.seek(0, 2)
print(f.tell())
with open('a.txt', mode='a+b') as f:
f.seek(-6, 2)
# print(f.read().decode('utf-8'))
print(f.read(3).decode('utf-8'))
import time
with open('a.txt', mode='rb') as f:
f.seek(0, 2)
while True:
line = f.readline()
if len(line) == 0:
time.sleep(0.1)
else:
print(line.decode('utf-8'), end="")
5.6 檔案修改的兩種方式
# 方式一:
# 1、以r模式開啟原始檔,將原始檔內容全部讀入記憶體
# 2、在記憶體中修改完畢
# 3、以w模式開啟原始檔,將修改後的內容寫入原始檔
# 優點:不必大量佔用硬碟資源
# 缺點:耗記憶體,需要足夠的記憶體空間
with open('a.txt', mode='rt', encoding='utf-8') as f1:
data = f1.read()
res = data.replace('hello', '早上好')
with open('a.txt', mode='wt', encoding='utf-8') as f2:
f2.write(res)
# 方式二:
# 1、以r模式開啟原始檔,然後以w模式開啟一個臨時檔案
# 2、從原始檔中讀一行到記憶體中,修改完畢後直接寫入臨時檔案,迴圈往復直到操作完畢所有行
# 3、刪除原始檔,將臨時檔名改為原始檔名
# 優點:沒有對記憶體造成過度的佔用
# 缺點:需要硬碟預留出足夠的空間來存放臨時檔案
import os
with open('a.txt', mode='rt', encoding='utf-8') as src_f,\
open('.a.txt.swp', mode='wt', encoding='utf-8') as dst_f:
for line in src_f:
dst_f.write(line.replace('你好', 'Hello'))
os.remove('a.txt')
os.rename('.a.txt.swp', 'a.txt')
5.7 Type hinting
# Type hinting
def add(x: int, y: int) -> int:
res = x + y
return res
print(add.__annotations__)
# {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}