编码简述

最近遇到一次编码问题,就想着了解一下各种编码方案,以为不难,实际上还是花了不短的时间才大致弄清楚了。

ISO-8859-1、GB2312、Unicode

    最初的计算机只需要表示字母,所以需要的空间很少。对应的一个标准就是ISO-8859-1,这个标准是单字节的,向下兼容ASCII,编码范围0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字字符,主要用来支持欧洲国家的语言。

    为了能够让计算机识别中文,那也必须有对应的字符集。最早,中国自己发布了GB2312,后来微软又在GB2312的基础上进行扩充就有了GBK,中国后来又继续扩充字符集,就有了GB18030。

    接着,为了表示日语、韩语、阿拉伯语...等等各种语言,又出现了很多种字符集。但这些字符集都限定在一个较狭窄的范围内,很难跨系统使用,毕竟编码方式不一样。为了统一编码,就有了Unicode。

Unicode

    Unicode规定必须使用两个字节,来统一标识所有字符,对于ASCII的字符,Unicode肯定也兼容,只是要扩展到16位,高8位为0。在Unicode中,无论是英文字母还是汉字,都是统一的“一个字符”,也都是统一的“两个字节”。在这里,字符是文化相关符号,字节是存储单元。

    Unicode在编码上与其它编码方案并不完全兼容,GBK和Unicode在内码编排上就不同,很难找到对应的规则和算法来转换,转换只能靠查表。


区别字符集和编码

    看了一些资料后,个人觉得可以简单的理解成

    字符集仅仅是规定了字符对应的二进制数字的集合,而编码就是规定怎么物理的存储这些二进制数字。

    (Unicode是一种字符集,UTF-8/UTF-16/UTF-32是字符编码方案)

     Unicode实际上就只是一个字符集,只规定了怎么表示各种字符的二进制数字,但没有规定到底要怎样来存储这些二进制数字。对于英文字母一个字节就够了,但对于某些字符可能需要3个或四个字节来表示,如果统一用4个字节来表示的话,那对于英文字母的存储就浪费太多空间了。

    而UTF-8就是一种Unicode字符集的实现方式,是在互联网上使用最广的。UTF(Unicode Transfer Format),UTF-8和Unicode并不是直接对应的, 要通过一些算法和规则才能转换。因为UTF-8是一种变长的编码方式,可以使用1-4个字节来表示一个符号,根据不同符号而变化字节长度,这样对于不同的字符就能够最大限度地节省存储空间了。具体对应关系可以自行查找。

UTF-8的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

下表总结了编码规则,字母x表示可用编码的位。

Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

下面,以汉字“严”为例,演示如何实现UTF-8编码。

已知“严”的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是“11100100 10111000 10100101”,转换成十六进制就是E4B8A5。


什么是大端序和小端序?对于(EC 8D)

    如果存储时,高位在前,低位在后,那就是大端序(大头方案)(EC 8D,存储时)

    如果存储时,低位在前,高位在后,那就是小端序(小头方案)(8D EC,存储时)

    Unicode规范中定义,每个文件的最前面分别加入一个表示编码顺序的字符,这个字符叫做“zero width no-break space”(零宽度非换行空格),用FFFE表示。

    如果是FE FF,就表示大端序;如果是FF FE,就表示小端序。

什么叫带BOM的编码?

    前面提到了Unicode只是字符集,有好几种实现它的编码方案,那怎么来区别到底使用的是什么编码呢?

    为了确定一段二进制数字到底是哪一种编码方案。就在文件的最前面保存一个标签,这个标签就叫做BOM(Byte Order Mark,字节序标记)。

    如果BOM是FF FE,那对应的编码就是UTF-16 little endian

    如果BOM是FE FF,那对应的编码就是UTF-16 big endian

    如果是EF BB BF,那对应的编码就是记事本下的UTF-8

    如果没有,则对应ANSI。

Windows下记事本中的四种编码方式:ANSI、Unicode、Unicode big endain、UTF-8

    ANSI并不是一种具体的编码方案,应该说是一种字符代码吧。是根据系统默认语言来决定的,表示当前系统的遗留编码。如果系统是简体中文,ANSI就是GB2312;如果是繁体中文,ANSI就是Big5;如果是日语,那又是另外一种编码。

    Unicode其实也并不是Unicode,实际上是带BOM的小端序的UTF-16编码,使用两个字节来存储字符的Unicode码。只是微软称作Unicode。

    Unicode big endian就是带BOM的大端序的UTF-16编码

    UTF-8 实际上是带BOM的UTF-8;也被微软简化了,对于程序开发确实还是会有点影响。

上面提到的两点可以很简单的验证,只要下载一个十六进制编辑器,我使用的是UltraEditor。

    首先用记事本提供的4种编码方式分别保存4份文件。

    然后UltraEditor的十六进制功能分别打开。就可以很清楚的看到文件最开始对应的十六进制数。对应关系,就是上面提到的那样。

为了验证记事本下的UTF-8和一般的UTF-8的区别。可以分别用 Notepad++ 的UTF-8无BOM格式编码和UTF-8格式编码创建两个新文件,然后在十六进制编辑器中打开,看前缀的十六进制数是什么样的。

编码转换带来的乱码:"锟斤拷"

  在GB2312等字符集,向Unicode转换时,总有一些不能很好的转换,或者有一些字符本身就非法的。Unicode规定以U+FFFD当作一个占位符来表示这些字符。那用UTF-8编码它就是EF BF BD,连续多个这样的字节序列出现就成了EF BF BD EF BF BD。如果用UTF-8来解析就是问号,如果用GBK解析,一个汉子两个字节,就变成了“锟斤拷”。

“烫烫烫”和“屯屯屯”

这样的乱码与编码转换无关,出现肯定是开了内存没有初始化。在VC的Debug模式下,会把未初始化的栈内存全部填成0xCC,未初始化的堆内存都填成0xCD。再使用GBK编码,CC CC 就是“烫”,CD CD 就是“屯”。现在回想起以前经常遇到这个乱码现象,但都没有想着要去搞清楚一下,真是太不会学习了。

终结一下:

    在程序开发中,还是尽量要明确指定所使用的编码方案比较好,这样不容易乱码。

  如果是程序相关内容,建议还是用更专业的文本编辑器来编写更好,起码会很明确的告知你使用的到底是什么编码,到底带不带BOM。

    使用记事本的话,要很清楚保存的编码格式是什么。

    如果要跨平台,跨系统,尽量使用不带BOM的UTF-8。对于PHP来说,带BOM的话可能会有很严重的问题。

    虽然花了蛮长的时间,但磨刀不误砍柴工,确实感觉还是收获了很多。


带 BOM 的 UTF-8」和「无 BOM 的 UTF-8」有什么区别?

编码歪传——番外篇

Windows 记事本的 ANSI、Unicode、UTF-8 这三种编码模式有什么区别?

各种编码UNICODE、UTF-8、ANSI、ASCII、GB2312、GBK详解


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值