05 python開發之檔案處理

drrug發表於2020-12-04

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'>}

相關文章