python之檔案操作及字元編碼
檔案操作的基本流程
我們使用Python或者其他語言編寫的應用程式,當我們需要一些資料的時候,可能是資料庫中的資料,也可能是計算機本身儲存的資料。當我們需要應用到計算機中的資料的時候,那麼我們就需要操作計算機中的檔案。而Python給我們提供了檔案操作的方法。檔案操作有三大步流程
#1. 開啟檔案,得到檔案控制代碼並賦值給一個變數
f=open('a.txt','r',encoding='utf-8') #預設開啟模式就為r
#2. 通過控制代碼對檔案進行操作
data=f.read()
#3. 關閉檔案
f.close()
一定要記得關閉檔案
當我們開啟一個檔案的時候,是佔用了我們的記憶體資源的,如果我們只打開檔案而不關閉,那麼將會一直損耗佔用我們的記憶體資源,直至記憶體資源被消耗完畢,卡死。所以,在操作完一個檔案的時候,一定要關閉檔案。關閉檔案有兩種方法:
f.close()
del f #回收應用程式級的變數
不過, del f 一定要發生在f.close() 之後,否則就會導致作業系統大開的檔案並沒有關閉,而白白浪費資源。而python自動的垃圾回收機制決定了我們無需考慮del f,這就要求我們,在操作完畢檔案後,一定要記住f.close()。當然,每一次開啟檔案之後都要關閉,也就是都要f.close()。有的時候,我們會忘記關閉,那麼還有一種簡便的方式。極力推薦:
with open(‘a.txt’,‘w’) as f:
pass
with open('a.txt','r') as read_f,open('b.txt','w') as write_f: data=read_f.read() write_f.write(data)
檔案編碼
f=open(…)是由作業系統開啟檔案,那麼如果我們沒有為open指定編碼,那麼開啟檔案的預設編碼就是作業系統說了算了,作業系統會用自己的預設編碼去開啟檔案,在windows下是gbk,在linux下是utf-8,所以,當我們開啟檔案的時候,一定要記得檔案編碼。
f=open(‘a.txt’,‘r’,encoding=‘utf-8’)
檔案開啟的模式
我們知道,在本地計算機中的檔案,有一些我們可以開啟閱讀並修改,但有一些卻只能檢視,甚至不能檢視。只就是我們對檔案進行了設定,設定它的開啟方式。在Linux中,就顯得格外的明顯了。那麼Python操作檔案的時候,也有相對應的開啟模式:
-
開啟檔案的模式有(預設為文字模式):
r ,只讀模式【預設模式,檔案必須存在,不存在則丟擲異常】
w,只寫模式【不可讀;不存在則建立;存在則清空內容】
a, 只追加寫模式【不可讀;不存在則建立;存在則只追加內容】 -
對於非文字檔案,我們只能使用b模式,"b"表示以位元組的方式操作(而所有檔案也都是以位元組的形式儲存的,使用這種模式無需考慮文字檔案的字元編碼、圖片檔案的jgp格式、視訊檔案的avi格式)
rb
wb
ab
注:以b方式開啟時,讀取到的內容是位元組型別,寫入時也需要提供位元組型別,不能指定編碼 -
+’模式(就是增加了一個功能)
r+, 讀寫【可讀,可寫】
w+,寫讀【可寫,可讀】
a+, 寫讀【可寫,可讀】 -
以bytes型別操作的讀寫,寫讀,寫讀模式
r+b, 讀寫【可讀,可寫】
w+b,寫讀【可寫,可讀】
a+b, 寫讀【可寫,可讀】*
檔案操作的具體方法
read(3):
1. 檔案開啟方式為文字模式時,代表讀取3個字元
2. 檔案開啟方式為b模式時,代表讀取3個位元組
其餘的檔案內游標移動都是以位元組為單位的如:seek,tell,truncate
注意:
-
seek有三種移動方式0,1,2,其中1和2必須在b模式下進行,但無論哪種模式,都是以bytes為單位移動的
-
truncate是截斷檔案,所以檔案的開啟方式必須可寫,但是不能用w或w+等方式開啟,因為那樣直接清空檔案了,所以truncate要在r+或a或a+等模式下測試效果
def close(self, *args, **kwargs): # real signature unknown
關閉檔案
pass
def fileno(self, *args, **kwargs): # real signature unknown
檔案描述符
pass
def flush(self, *args, **kwargs): # real signature unknown
重新整理檔案內部緩衝區
pass
def isatty(self, *args, **kwargs): # real signature unknown
判斷檔案是否是同意tty裝置
pass
def read(self, *args, **kwargs): # real signature unknown
讀取指定位元組資料
pass
def readable(self, *args, **kwargs): # real signature unknown
是否可讀
pass
def readline(self, *args, **kwargs): # real signature unknown
僅讀取一行資料
pass
def seek(self, *args, **kwargs): # real signature unknown
指定檔案中指標位置
pass
def seekable(self, *args, **kwargs): # real signature unknown
指標是否可操作
pass
def tell(self, *args, **kwargs): # real signature unknown
獲取指標位置
pass
def truncate(self, *args, **kwargs): # real signature unknown
截斷資料,僅保留指定之前資料
pass
def writable(self, *args, **kwargs): # real signature unknown
是否可寫
pass
def write(self, *args, **kwargs): # real signature unknown
寫內容
pass
def __getstate__(self, *args, **kwargs): # real signature unknown
pass
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass
def __repr__(self, *args, **kwargs): # real signature unknown
""" Return repr(self). """
pass
檔案修改
檔案的資料是存放於硬碟上的,因而只存在覆蓋、不存在修改這麼一說,我們平時看到的修改檔案,都是模擬出來的效果,具體的說有兩種實現方式:
方式一:將硬碟存放的該檔案的內容全部載入到記憶體,在記憶體中是可以修改的,修改完畢後,再由記憶體覆蓋到硬碟
import os # 呼叫系統模組
with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
data=read_f.read() #全部讀入記憶體,如果檔案很大,會很卡
data=data.replace('www','happy') #在記憶體中完成修改
write_f.write(data) #一次性寫入新檔案
os.remove('a.txt') #刪除原檔案
os.rename('.a.txt.swap','a.txt') #將新建的檔案重新命名為原檔案
方式二:將硬碟存放的該檔案的內容一行一行地讀入記憶體,修改完畢就寫入新檔案,最後用新檔案覆蓋原始檔
import os
with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
for line in read_f:
line=line.replace('www','happy')
write_f.write(line)
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')
關於編碼
asiic
包含數字,英文,特殊字元。利用八位表示一個字元
8位 = 1 byte 表示一個字元。
萬國碼unicode
將所有國家的語言包含在這個密碼本。
初期:16位,兩個位元組,表示一個字元。
A : 00010000 00010010
中: 00010010 00010010
升級:32位,四個位元組,表示一個字元。
A : 00010000 00010010 00010000 00010010
資源浪費。
utf-8
最少用8位(一個位元組),表示一個字元。
英文:a :00010000 用8位表示一個字元。
歐洲:00010000 00010000 16位兩個位元組表示一個字元。
亞洲 中 :00010000 00010000 00010000 24位,三個位元組表示一個字元。
gbk:國標
只包含:英文中文。
英文:a :00010000 8位,一個位元組表示一個字元。
中文:中:00010000 00010000 16位,兩個位元組表示一個字元。
gb2312…
計算機單位之間的划算
8 bit = 1byte
1024byte=1kb
1024kb = 1MB
1024MB = 1GB
1024GB = 1TB
編碼與解碼
encode 編碼 :str — > bytes
s = 'aAlice' # str
s1 = s.encode('utf-8') # bytes
encode 編碼。gbk–>utf-8
s = 'hello girl'
s1 = s.encode('gbk')
print(s1)
s = '中國'
s1 = s.encode('utf-8')
print(s1)
unicode —> utf-8 編碼 與解碼:
s = 'alex'
s1 = s.encode('utf-8') # unicode ---> utf-8 編碼
s3 = s1.decode('utf-8') # utf-8 ---> unicode 解碼
print(s3)
unicode —> gbk 編碼與解碼:
s = 'alex'
s1 = s.encode('gbk') # unicode ---> gbk 編碼
s3 = s1.decode('gbk') # gbk ---> unicode 解碼
print(s3)
gbk —> utf-8
s = 'alex'
s1 = s.encode('gbk')
print(s1)
s2 = s1.decode('gbk').encode('utf-8')
print(s2)
需要說的是:Linux的作業系統預設的編碼是utf-8,Windows作業系統是gbk編碼,Python中預設的編碼是utf-8,所以,需要注意python與Windows作業系統之間的關係。