Day12 檔案操作(1)

Little Yueyue發表於2020-11-03

一個完整的程式一般都包括資料的儲存和讀取; 但python 直譯器執行完資料就消失了。實際開發中,經常需要從外部儲存介質(硬碟、光碟、U 盤等)讀取資料,或者將程式產生的資料儲存到檔案中,實現“持久化”儲存。
很多軟體系統是將資料儲存的資料庫中; 資料庫實際也是基於檔案形式儲存的。

文字檔案和二進位制檔案

資料組織形式儲存開啟軟體
文字檔案普通“字元文字”,預設unicode字符集( 2 16 2^{16} 216個字元)可用記事本開啟
二進位制檔案用“位元組”進行儲存專用軟體解碼

二進位制檔案更為常見。

檔案操作相關模組概述

名稱說明
io 模組檔案流的輸入和輸出操作 input output
os 模組基本作業系統功能,包括檔案操作
glob 模組查詢符合特定規則的檔案路徑名
fnmatch 模組使用模式來匹配檔案路徑名
fileinput 模組處理多個輸入檔案
filecmp 模組用於檔案的比較
cvs 模組用於 csv 檔案處理
pickle 和 cPickle用於序列化和反序列化
xml 包用於 XML 資料處理
bz2、 gzip、 zipfile、 zlib、 tarfile用於處理壓縮和解壓縮檔案(分別對應不同的演算法)

建立檔案物件 open()

語法格式

open(檔名[,開啟方式])

note:
1.檔名可以錄入全路徑,比如:D:\a\b\c.txt。為了減少“\”的輸入,可以使用原始字串:r“d:\b.txt”(路徑前加上r),示例:f = open(r"D:\a\b\c.txt",“w”)
2.

開啟方式描述
r讀 read 模式
w寫 write 模式。如果檔案不存在則建立;如果檔案存在,則重寫新內容;
a追加 append 模式。如果檔案不存在則建立;如果檔案存在,則在檔案末尾追加內容
b二進位制 binary 模式(可與其他模式組合使用)
+讀、寫模式(可與其他模式組合使用)
  1. 如果我們沒有增加模式“b”,則預設建立的是文字檔案物件,處理的基本單元是“字元”。如果是二進位制模式“b”,則建立的是二進位制檔案物件,處理的基本單元是“位元組”。

文字檔案的寫入

建立檔案物件
寫入資料
關閉檔案物件

需要關閉相關檔案和作業系統的資源。

呼叫作業系統
PY檔案
直譯器執行檔案
寫入硬碟
f=open(r'E:\PycharmProjects\excpt\edit.txt','w')
f.write('yueyue is lively!')
f.close()

常用編碼

一般專案都會使用 UTF-8。
在這裡插入圖片描述

中文亂碼問題

windows 作業系統預設的編碼是 GBK,Linux 作業系統預設的編碼是 UTF-8。

Unicode執行
作業系統預設GBK編碼
PY檔案UTF-8解碼
直譯器呼叫作業系統
寫入硬碟

可命令作業系統建立檔案時用UTF-8

f=open(r'E:\PycharmProjects\excpt\edit.txt','w',encoding='utf-8')
f.write('悅悅最可愛!')
f.close()

write()/writelines()寫入資料

write(a):把字串a寫入到檔案中,每次寫完會換行
writelines(b):把字串列表b寫入檔案中,不會自動換行(即不新增換行符),而是將列表元素全部連線在一起。

f=open(r'E:\PycharmProjects\excpt\edit.txt','w',encoding='utf-8')
s1='yueyue\nlively\nsmart\n'
f.write(s1)
s2=['yueyue\n','lively\n','smart\n']
f.writelines(s2)
f.close()
# yueyue
# lively
# smart
# yueyue
# lively
# smart

close()關閉檔案流

呼叫外部作業系統,會開啟作業系統的相關資源和物件
python程式
在硬碟找到檔案並操作
  1. 由於檔案底層是由作業系統控制,故開啟的檔案物件必須顯式呼叫 close()方法關閉檔案物件利用try…finally結構或者 with 關鍵字實現
try:
    f=open('edit.txt','a')
    s=['a,s,d']
    f.writelines(s)
except BaseException as e:
    print(e)
finally:
    f.close()

在這裡插入圖片描述
2. 當呼叫 close()方法時, 首先會把緩衝區資料寫入檔案(也可以直接呼叫 flush()方法),再關閉檔案,釋放檔案物件

with 語句(上下文管理器)

不論什麼原因跳出 with 塊,都能確保檔案正確的關閉,並且可以在程式碼塊執行完畢後自動還原進入該程式碼塊時的現場。

s=['h','a','p','p','y']
with open('edit.txt','a') as f:
    f.writelines(s)

文字檔案的讀取

基本操作

方法說明示例
read([size])讀取 size 個字元,並作為結果返回。預設讀取整個檔案。
讀取到檔案末尾,會返回空字串。
f.read()
readline()讀取一行內容作為結果返回。
讀取到檔案末尾,會返回空字串。
f,readline()
readlines()文字檔案中,每一行作為一個字串存入列表中,返回該列表f,readlines()

note:中文也是每個字一個字元。

#讀取前幾個字元
with open(r'edit.txt','r',encoding='utf-8') as f:
    print(f.read(3))

#按行讀取檔案
#方法1
with open(r'edit.txt', 'r', encoding='utf-8') as f:
    for line in f:
        print(line,end='')  #檔案每行末尾預設有換行符
#方法2
with open(r'edit.txt','r',encoding='utf-8') as f:
    while  True:
        line=f.readline()
        if not line:
            break
        else:
            print(line,end='')

為每一行加序號

enumerat()函式

將索引與對應列表元素以元組構成的enumerate物件返回

a=['yueyue','lively','cute','smart','happy']
b=enumerate(a)
print(b)
#<enumerate object at 0x0000024452213F48>
print(list(b))
#[(0, 'yueyue'), (1, 'lively'), (2, 'cute'), (3, 'smart'), (4, 'happy')]
c=[temp+'#'+str(index) for index,temp in enumerate(a)]
print(c)
#['yueyue#0', 'lively#1', 'cute#2', 'smart#3', 'happy#4']

檔案示例

with open(r'edit.txt','r',encoding='utf-8') as f:
    lines=f.readlines()
    content=[temp.rstrip()+' '+str(index+1)+'\n' for index,temp in enumerate(lines)]
    print(content)

with open('edit2.txt','w',encoding='utf-8')as f:
    f.writelines(content)

二進位制檔案的讀取和寫入

二進位制檔案的處理流程和文字檔案流程一致。需要指定二進位制模式,從而建立出二進位制檔案物件。例如:
f = open(r"e:\a.txt", ‘wb’) #可寫的、重寫模式的二進位制檔案物件
f = open(r"e:\a.txt", ‘ab’) #可寫的、追加模式的二進位制檔案物件
f = open(r"e:\a.txt", ‘rb’) #可讀的二進位制檔案物件
note: \quad 建立好二進位制檔案物件後,仍然可以使用 write()、read()實現檔案的讀寫操作。

with open(r'D:\桌面\11.jpg','rb') as f:
    with open('edit2.jpg','wb')as w:
        for line in f.readlines():
            w.write(line)

檔案物件的常用屬性和方法

檔案物件封裝了檔案相關的操作。

檔案物件的屬性說明
name返回檔案的名字
mode返回檔案的開啟模式
closed若檔案被關閉則返回 True
檔案物件的其他常用方法說明
seek(offset[,whence])把檔案指標移動到新的位置, offset 表示相對於 whence 的多少個位元組的偏移量;
offset:offset 為正往結束方向移動,為負往開始方向移動
whence 不同的值代表不同含義:
0: 從檔案頭開始計算(預設值)
1:從當前位置開始計算
2:從檔案尾開始計算
tell()返回檔案指標的當前位置
truncate([size])不論指標在什麼位置,只留下指標前 size 個位元組的內容,其餘全部刪除;如果沒有傳入 size,則當指標當前位置到檔案末尾內容全部刪除
flush()把緩衝區的內容寫入檔案,但不關閉檔案
close()把緩衝區內容寫入檔案,同時關閉檔案,釋放檔案物件相關資源

note: 上述說的是位元組,utf-8中,一個漢字3個位元組,一個字母一個位元組,注意讀取行的時候末尾還有換行符/n算兩個位元組

# yueyue
# lively
# cute
# smart
with open(r'edit.txt','r') as f:
    print('檔名:{}   檔案開啟模式:{}'.format(f.name,f.mode))
    #檔名:edit.txt   檔案開啟模式:rb
    print('指標的當前位置:{}'.format(f.tell()))
    #指標的當前位置:0
    print('第一行的內容:{}   當前位置:{}'.format(f.readline(),f.tell()))
    # 第一行的內容: yueyue
    # 當前位置:8
    print('第二行的內容:{}   當前位置:{}'.format(f.readline(), f.tell()))
    # 第二行的內容: lively
    # 當前位置:16
    f.seek(0)
    print('指標的當前位置:{}'.format(f.tell()))
    # 指標的當前位置:0

pickle 序列化

序列化指的是:將物件轉化成“序列化”資料形式,儲存到硬碟或通過網路傳輸到其他
地方。
反序列化:將讀取到的“序列化資料”轉化成物件。
示例:

序列化
反序列化
記憶體中的物件
儲存在硬碟

pickle 模組中的函式,課實現序列化和反序列操作。

操作說明
pickle.dump(obj, file)obj 就是要被序列化的物件,file 指的是儲存的檔案
pickle.load(file)從 file 讀取資料,反序列化成物件

note:反序列化取出的順序和序列化存入的順序是一致的。

import pickle
a1='yueyue'
a2='lively'
a3='happy'
with open('edit.gif','wb')as f:
    pickle.dump(a1,f)
    pickle.dump(a2, f)
    pickle.dump(a3, f)

with open('edit.gif','rb') as f:
    b1=pickle.load(f)
    b2= pickle.load(f)
    b3 = pickle.load(f)
    print(b1,b2,b3)#注意他和存入的順序是一致的

print(id(a1),id(b1)) #雖然是序列化存入,反序列化取出,內容一樣,但是不同的物件