UTF-8、GB231、GBK编码格式
UTF-8编码
使用1~4个字节对每个字符进行编码,为了性能考虑,做成了一种可变长度的编码规范。
每种字符集需要的编码字节长度
- 128个ASCII字符只需要一个字节进行编码
- 带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要两个字节进行编码
- 其他基本多文种平面中的字符(这包含了大部分常用字,如大部分的汉字)使用三个字节进行编码
- 其他极少使用的Unicode辅助平面的字符使用四至六字节进行编码
GB2312编码
- 一个小于127的字符意义与原来的相同,将两个大于127的字符连在一起,就表示一个汉字;
- 前面的一个字节(高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE;
其中,在ASCII里本来就有个的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的“全角”字符,而原来在127号以下的那些就叫“半角”字符
GBK编码
是GB2312编码的一种扩展,不再要求低字节一定是127号之后的编码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容
示例
仅仅从文字介绍来看比较抽象,看完后也还是一头雾水,借助于nodejs,我们可以研究一下实际的案例,方便对比和理解。
纯汉字内容编码
以【联通】这两个汉字为例,参考一个两种编码格式的输出产物。
------------------GB2312编码保存的[联通]数据------------------
<Buffer c1 aa cd a8>
------------------UTF-8编码保存的[联通]数据-带BOM------------------
<Buffer ef bb bf e8 81 94 e9 80 9a>
------------------UTF-8编码保存的[联通]数据-不带BOM------------------
<Buffer e8 81 94 e9 80 9a>
可以清楚看到GB2312和UTF-8编码格式的区别:GB2312使用两个字节对汉字进行编码,而UTF-8使用三个字节对汉字进行编码
其中还着重列出了UTF-8编码的两种规范,带BOM头 VS 不带BOM头的区别,在日常中也是两种比较常见的实践。
UTF-8带BOM的编码格式和不带BOM的编码格式之间的区别:BOM格式会在头部添加ef bb bf三个字节作为标志
中英文混合内容编码
这个主要是看各个编码格式对于ASCII编码的兼容情况,以【hello 你好】内容为例,进行编码内容分析。
------------------非UTF-8编码保存的[hello 你好]数据------------------
<Buffer 68 65 6c 6c 6f 20 c4 e3 ba c3>
------------------UTF-8编码保存的[hello 你好]数据-带BOM------------------
<Buffer ef bb bf 68 65 6c 6c 6f 20 e4 bd a0 e5 a5 bd>
------------------UTF-8编码保存的[hello 你好]数据-不带BOM------------------
<Buffer 68 65 6c 6c 6f 20 e4 bd a0 e5 a5 bd>
从上面的两种编码输出结果,可以有以下结论:
- 两种编码格式对ASCII都能兼容,前面的[hello ]两者的编码是一致的,而中文字符编码则是根据各自不同的编码规则来得
- 如果只有ASCII字符,则两种编码是等价的,GB2312方式打开UTF-8编码的文件不会出现乱码,反之亦然
自动编码格式校验
在日常中经常进行文件的传输,在使用编辑器打开别人传输过来的文件时,如果编码格式对不上就会出现乱码的情况。考虑是不是存在一种自动转换的方法,在不同的编码格式间进行自动转换,避免出现乱码的情况。以下是自己在这方面针对UTF-8和GB2312编码格式识别的思考:
- 带有BOM信息的,可以根据BOM信息进行区分:前三个字节为:ef bb bf的是UTF-8编码格式
- 没有BOM信息的,则需要按字节进行区分:如果UTF-8中有中文字符,则可以根据1110XXXX 10XXXXXX 10XXXXXX这种格式来进行区分;如果UTF-8中有其他两个字节编码的字符则较难进行区分
经过在对用户上传文件进行分析,感觉实用性还是蛮好的。