05 python開發之文件處理
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'>}