对于一段输入,很重要的一个方面就是判断输入采用了何种编码方式。只有知道了编码方式,对输入进行解码成有意义的字符串,才能够进行后续的操作。但是有的时候并不知道输入的编码方式,就需要手动的进行判断。本文手动编写判断程序判断字节串是否为utf8为例进行介绍,使得大家了解字节串判断编码的大致原理 。后续会介绍一些通过已有的判断模块进行介绍。手动编写的判断程序如下:
def is_UTF_8(text):
remain = 0 #剩余byte数
for x in range(len(text)):
if remain == 0:
if (ord(text[x]) & 0x80) == 0x00:
remain = 0
elif (ord(text[x]) & 0xE0) == 0xC0:
remain = 1
elif (ord(text[x]) & 0xF0) == 0xE0:
remain = 2
elif(ord(text[x]) & 0xF8) == 0xF0:
remain = 3
else:
return False
else:
if not ((ord(text[x]) & 0xC0) == 0x80):
return False
remain = remain - 1
if remain == 0: #最后如果remain不等于零,可能没有匹配完整
return True
else:
return False
def existBOM(file_name):
fileHandler = open(file_name,'r')
code =fileHandler.read(3)
fileHandler.close()
if code == codecs.BOM_UTF8:#判断是否包含EF BB BF
return True
return False
由于UTF8包含两种编码情况,如下图中的nodepad++所示:
因此检测程序需要包含两个方面的内容:
1,函数is_UTF_8检测UTF8无BOM格式编码
2,函数existBOM检测UTF8有BOM 头的格式编码,其实从程序可知有BOM就是在文件的开头多了三个字节,即EF BB BF。
理解上述程序需要简单的了解一下UTF 8的编码原理。下图表示的就是UTF8的编码规则:
左侧对应的是unicode代码点对应的取值,右侧对应的是UTF8编码之后的值,黑色部分固定,红色部分是需要填充的具体unicode的代码点对应的值。总的原则就是根据unicode代码点的范围,确定对应的utf8编码长度以及对应的格式。将unicode代码点转换成为二进制之后,依次的将该二进制从右向左的值对应填入上述编码格式中红色部分的从右向左的位置上,剩余的位置补齐0即可。
举两个例子来说明上表:
1,字符a对应的unicode值为0x0061,其二进制为1100001,对应上表中的第一行的存储方式,需要一个字节存储,因此从右向左的依次放入对应的位置得到存储内容为01100001,即0x61。
2,汉字‘中’对应的unicode值为0x4E2D,其二进制为100111000101101,其范围对应上表中的第三行的存储方式,需要三个字节存储,因此从后向前的依次放入对应的位置得到存储内容为111001001011100010101101,即0xE4B8AD。
上述代码中的四个判断对应的就是表格中的四种情况,当你了解utf8具体的编码步骤之后,应该很容易的明白代码,remain表示的就是utf8编码的字节长度减1。UTF8的编码规则还保证了每一个Unicode代码点对一对应的编码值不会是其他范围的一个子集,因此不会出现编码的歧义问题。
另外我还发现站长之家给出工具,将中文转换成为utf8的结果其实是unicode代码点,并不是utf8编码的值。当然关于编码,有好多的内容,后续会单独的写一篇进行分享。
本文为优快云村中少年原创文章,转载记得加上小尾巴偶,博主链接这里。