1. 程式人生 > 實用技巧 >編碼轉換:UTF-8 BOM to GBK

編碼轉換:UTF-8 BOM to GBK

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

編碼轉換:UTF-8 BOM to GBK

最近因為一個實驗,需要文字檔案的編碼格式為GBK或者GB2312,而源數 據又是很多編碼格式的,有些是GBK,有些是UTF-8,這樣就不好用工具直接轉,手動就更不可取了,於是打算寫個程式,能夠讀取UTF-8的檔案,更改編碼後,再寫入另一個檔案,存為GBK格式。

在網上看了很多例子,也查了python API,發現都不完整,原因就在於都沒考慮到有BOM和無BOM兩種情況。也有說用codecs.EncodedFile(...)來做的,試了很多次,無論是有BOM還是無BOM,轉成GBK都失敗。

下面來看我的試驗過程。

1.無BOM的UTF-8轉GBK

首先用ultraedit新建一個文字檔案,並存為UTF-8 無BOM格式,我的叫“u8.txt”,內容為“試 試 這 個”,帶回車換行,並且字元間加了空格,以便定位;

其次,寫程式碼測試:

importcodecs

f =open("u8.txt", "r");
data = f.read();
print repr(data)
print data.decode("utf-8").encode("gbk")

s = '/xe8/xbf/x99 /xe4/xb8/xaa';

print s.decode("utf-8").encode("gbk")
f.close();

執行檢視結果:

讀取utf8無BOM的檔案

根據輸出可見,第一行是4個漢字字元的UTF-8編碼,每個字元佔3個位元組,最後跟著一個換行符;第二行是編碼為GBK後列印的結果,說明編碼轉換沒有問題;注意字串s的內容為我手工擷取的最後兩個字元的位元組編碼,即“這 個”,對s先解碼再編碼成GBK後,成功輸出。

由此可知,無BOM的UTF-8轉換成GBK是很容易的。

2.有BOM的UTF-8轉GBK

首先,仍然用ultraedit新建一個文字檔案,但是需要儲存為UTF-8,這就是有BOM的格式,我的是“char.txt”,內容為“老 子 不 信 轉 不 過 來”,也是帶空格以便定位字元,仍然用上面的程式碼執行,結果為:

讀取UTF8帶BOM

出現錯誤!提示說無法對0位元組處採用GBK編碼,再看顯示出的編碼序列,發現最開頭那段6個位元組連在一起,但是我們的字串分明是按空格分開的!怎麼回事?!通過查wikipedia發現:

BOM

原來最開始的“/xef/xbb/xbf”是UTF-8的BOM!那是不是因為這個BOM才造成編碼轉換失敗的呢?可以複製BOM後面的內容作為字串s的內容,寫程式碼測試,程式碼如下:

s = '/xe8/x80/x81 /xe5/xad/x90 /xe4/xb8/x8d /xe4/xbf/xa1 /xe8/xbd/xac /xe4/xb8/x8d /xe8/xbf/x87 /xe6/x9d/xa5/n'

print s.decode("utf-8").encode("gbk")
執行後發現,轉換成功進行,這就是說,只要能在轉換前去掉BOM,那麼就能轉換成功。
根據上面的心得,我寫了下面的程式碼測試:

程式碼

程式碼說明:bom為讀取檔案前3個位元組的內容,codecs.BOM_UTF8代表的就是utf8 BOM的位元組編碼,前面已經提到了。if語句判斷是否為UTF8 BOM格式,如果是,我們就從檔案的第3個位元組開始讀檔案,以便避開BOM,然後就是轉換,最後成功輸出。

結果

程式碼中“注意”那行打印出位元組編碼,可見,字元已被轉換成2 Bytes per character的GBK編碼格式。

結束語:這裡只寫了UTF8格式的,UTF16的道理也一樣,只是UTF16的BOM只有兩個位元組,具體可見上面的BOM表示的圖。總結起來說就是:UTF8轉GBK本來是很容易的,因為字元都對應,只是因為有了BOM,使問題變得麻煩些,不過弄懂了原理也不復雜

轉載於:https://my.oschina.net/ypimgt/blog/89598