1. 程式人生 > >python之檔案操作及字元編碼

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操作檔案的時候,也有相對應的開啟模式:

  1. 開啟檔案的模式有(預設為文字模式):
    r ,只讀模式【預設模式,檔案必須存在,不存在則丟擲異常】
    w,只寫模式【不可讀;不存在則建立;存在則清空內容】
    a, 只追加寫模式【不可讀;不存在則建立;存在則只追加內容】

  2. 對於非文字檔案,我們只能使用b模式,"b"表示以位元組的方式操作(而所有檔案也都是以位元組的形式儲存的,使用這種模式無需考慮文字檔案的字元編碼、圖片檔案的jgp格式、視訊檔案的avi格式)
    rb
    wb
    ab
    注:以b方式開啟時,讀取到的內容是位元組型別,寫入時也需要提供位元組型別,不能指定編碼

  3. +’模式(就是增加了一個功能)
    r+, 讀寫【可讀,可寫】
    w+,寫讀【可寫,可讀】
    a+, 寫讀【可寫,可讀】

  4. 以bytes型別操作的讀寫,寫讀,寫讀模式
    r+b, 讀寫【可讀,可寫】
    w+b,寫讀【可寫,可讀】
    a+b, 寫讀【可寫,可讀】*

檔案操作的具體方法

read(3):

1. 檔案開啟方式為文字模式時,代表讀取3個字元

2. 檔案開啟方式為b模式時,代表讀取3個位元組

其餘的檔案內游標移動都是以位元組為單位的如:seek,tell,truncate

注意:

  1. seek有三種移動方式0,1,2,其中1和2必須在b模式下進行,但無論哪種模式,都是以bytes為單位移動的

  2. 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作業系統之間的關係。