字符編碼codecs模塊(讀寫文件)

python對多國語言的處理是支持的很好的,它能夠處理如今任意編碼的字符,這裏深刻的研究一下python對多種不一樣語言的處理。
有一點須要清楚的是,當python要作編碼轉換的時候,會藉助於內部的編碼,轉換過程是這樣的:
原有編碼 -> 內部編碼 -> 目的編碼 
python的內部是使用unicode來處理的,可是unicode的使用須要考慮的是它的編碼格式有兩種,一是UCS-2,它一共有65536個碼 位,另外一種是UCS-4,它有2147483648g個碼位。對於這兩種格式,python都是支持的,這個是在編譯時經過--enable- unicode=ucs2或--enable-unicode=ucs4來指定的。那麼咱們本身默認安裝的python有的什麼編碼怎麼來肯定呢?有一個 辦法,就是經過sys.maxunicode的值來判斷: python

import  sys
print  sys.maxunicode程序員


若是輸出的值爲65535,那麼就是UCS-2,若是輸出是1114111就是UCS-4編碼。
咱們要認識到一點:當一個字符串轉換爲內部編碼後,它就不是str類型了!它是unicode類型:shell

a  =   " 風捲殘雲 " 
print  type(a)
b  =  unicode(a,  " gb2312 " )
print  type(b)緩存

輸出:
<type 'str'>
<type 'unicode'>

這個時候b能夠方便的任意轉換爲其餘編碼,好比轉換爲utf-8:函數

c  =  b.encode( " utf-8 " )
 print  c編碼

c輸出的東西看起來是亂碼,那就對了,由於是utf-8的字符串。
好了,該說說codecs模塊了,它和我上面說的概念是密切相關的。codecs專門用做編碼轉換,固然,其實經過它的接口是能夠擴展到其餘關於代碼方面的轉換的,這個東西這裏不涉及。code

codecs模塊中重要的函數之一是lookup,它只有一個參數encoding,指的是編碼方式的名稱,即utf-8或者gb2312等等。對象

lookup函數返回一個包含四個元素的TUPLE,其中t[0]是encoder的函數引用,t[1]是decoder的函數引用,t[2] 是UTF-8編碼方式的StreamReader類對象引用,t[3]是UTF-8編碼方式的StreamWriter類對象引用相信對Python熟悉的你確定知道接下來該怎麼用它們了。接口

 codecs模塊還提供了方便程序員使用的單獨函數,以簡化對lookup的調用。它們是:utf-8

  • getencoder(encoding)
  • getdecoder(encoding)
  • getreader(encoding)
  • getwriter(encoding)

若是咱們只是想獲取一種utf-8編碼的encoder方法,那麼只須要這樣作:

>>> encoder = codecs.getencoder("utf-8")

 

上面的代碼就是codecs的使用,是最多見的用法。另外還有一個問題就是,若是咱們處理的文件裏的字符編碼是其餘類型的呢?這個讀取進行作處理也須要特殊的處理的。codecs也提供了方法.

python讀寫文件估計你們都用open內置函數,或者file這個工廠函數,這兩個的效果基本同樣。

打開文件的方式通常爲:f=open(file_name,access_mode = 'r',buffering = -1)。file_name就是文件的路徑加文件名字,不加路徑則文件會存放在python程序的路徑下,

access_mode就是操做文件的模式,主要有r,w,rb,wb等,細節網上一大堆,buffering = -1是用於指示訪問文件所採用的緩存方式。0表示不緩存;1表示只緩存一行,n表明緩存n行。若是不提供或爲負數,則表明使用系統默認的緩存機制。

打開之後就是寫和讀的操做。可是用open方法打開會有一些問題。open打開文件只能寫入str類型,無論字符串是什麼編碼方式。例如

>>> fr = open('test.txt','a')
>>> line1 = "我愛祖國"
>>> fr.write(line1)

這樣是徹底能夠的。可是有時候咱們爬蟲或者其餘方式獲得一些數據寫入文件時會有編碼不統一的問題,因此就通常都統一轉換爲unicode。此時寫入open方式打開的文件就有問題了。例如

>>> line2 = u'我愛祖國'
>>> fr.write(line2)

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    fr.write(line2)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-11: ordinal not in range(128)
>>>

怎麼辦,咱們能夠將上面的line2編碼成str類型,可是太麻煩。咱們要把獲得的東西先decode爲unicode再encode爲str。。。

input文件(gbk, utf-8...)   ----decode----->   unicode  -------encode------> output文件(gbk, utf-8...)

代替這繁瑣的操做就是codecs.open,例如

>>> import codecs
>>> fw = codecs.open('test1.txt','a','utf-8')
>>> fw.write(line2)
>>>

不會報錯,說明寫入成功。這種方法能夠指定一個編碼打開文件,使用這個方法打開的文件讀取返回的將是unicode。寫入時,若是參數 是unicode,則使用open()時指定的編碼進行編碼後寫入;若是是str,則先根據源代碼文件聲明的字符編碼,解碼成unicode後再進行前述 操做。相對內置的open()來講,這個方法比較不容易在編碼上出現問題。

# -*- encoding: gb2312 -*- 

import  codecs, sys
 #  用codecs提供的open方法來指定打開的文件的語言編碼,它會在讀取的時候自動轉換爲內部unicode 
 bfile  =  codecs.open( " dddd.txt " ,  ' r ' ,  " big5 " )
 # bfile = open("dddd.txt", 'r') 
 
ss  =  bfile.read()
 bfile.close()
 #  輸出,這個時候看到的就是轉換後的結果。若是使用語言內建的open函數來打開文件,這裏看到的一定是亂碼 
 print  ss, type(ss)

總結一下,codecs模塊爲咱們解決的字符編碼的處理提供了lookup方法,它接受一個字符編碼名稱的參數,並返回指定字符編碼對應的 encoder、decoder、StreamReader和StreamWriter的函數對象和類對象的引用。爲了簡化對lookup方法的調用, codecs還提供了getencoder(encoding)、getdecoder(encoding)、getreader(encoding)和 getwriter(encoding)方法;進一步,簡化對特定字符編碼的StreamReader、StreamWriter和 StreamReaderWriter的訪問,codecs更直接地提供了open方法,經過encoding參數傳遞字符編碼名稱,便可得到對 encoder和decoder的雙向服務。

相關文章
相關標籤/搜索