python提供的unicode转换不像iconv或是mbstowcs之类的方便。



如果转换一段 unicode("1234中文",’ascii’) 到utf8会直接出现UnicodeDecodeError的错误。如果在你能预知字串符的编码的时候,比如你用unicode(‘1234中文’, ‘gbk’) 就不会出现错误,不过很多时候,会出现CJK混合的情况,如果要做到将一段CJK文件转换成unicode可能就行不通了。



好在python的codecs提供了register_error这个功能:

register_error( name, error_handler)



原理很简单,不过要先看unicode是如何处理异常的,unicode这个函数是将一段string按输入的编码转换成目标的编码,如果出现了不与输入编码相符的,会出现一个UnicodeDecodeError的异常,通常有三种处理方法:strict,replace,ignore,默认是 strict,就是直接raise UnicodeDecodeError. 通过register_error,我们也可以有自己的处理方法,如果遇到与输入的编码不符的时候,我们就自己识别,比如GBK的,比如BIG5,比如 JP的。





def cjk_replace(exc):

if not isinstance(exc, UnicodeDecodeError):

raise TypeError("don’t know how to handle %r" % exc)



if exc.end + 1 > len(exc.object):

raise TypeError(‘unknown codec ,the object too short!’)



ch1 = ord(exc.object[exc.start:exc.end])

newpos = exc.end + 1

ch2 = ord(exc.object[exc.start + 1:newpos])

sk = exc.object[exc.start:newpos]





if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0x7E<=ch2<=0xFE): # GBK

return (unicode(sk,’cp936′), newpos)



if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5

return (unicode(sk,’big5′), newpos)



raise TypeError(‘unknown codec !’)



codecs.register_error("cjk_replace", cjk_replace)



我们的cjk_replace现在只能处理GBK与BIG5的,因为我对编码也不是特别了解,所以就大概知道GBK与BIG5的,JP的不知道是什么.在 cjk_replace这个函数里,我们对不认识的文字进行手工识别,如果认识的编码,就用正确的方法,并返回编码后的内容与新的pos,

比如"1234中文",在pos为4的时候,会调用我们的cjk_replace,我们会返回一个从gbk转换成utf8的’中‘字,并返回下个正确的位置‘文’的起始位置。当然了,处理‘文’的时候,还会再调用一次。T_T



看看是如何使用的

filedata = open(‘test.txt’,’r).read() #gbk and big5 file

data = unicode(filedata,’ascii’,’cjk_replace’).encode(‘utf8’)