漫谈计算机编码:从ASCII码到UTF-8
第一阶段 盘古开天辟地——ASCII码
计算机大家都知道,本质是二进制运算和存储。在计算机中人类的几乎所有文字和字符都没法直接表示,所以美国人在发明计算机的时候为了让计算机可以用于保存和传输文字,就发明了ASCII码(American Standard Code for Information Interchange,美国信息交换标准代码),用128个数字分别映射到美国人常用的一些字符,包括阿拉伯数字和26个英文字母的大小写,以及其他一些常用的符号。一个字符占用7位二进制,用一个字节byte(8位)来存储。
这样一来就满足了美国人的交流需要。
第二阶段 军阀混战之战国七雄——GBK
但是计算机这东西真的是太好用了,只在美国使用有点暴殄天物,其他国家为了能让计算机在自己国家也好用,就发明了自己的编码系统来适配自己国家的文字和字符,比如西欧国家的Windows-1252和中国的GBK以及港澳台地区用得比较多的Big5。
因为ASCII只有128个,用二进制7位就够了,而计算机的最小存储单位byte是8位,所以ASCII码中每个字节的最高位永远是0,因此这些国家在搞自己的编码的时候很容易地就保持了对ASCII的兼容,即当每个字节最低位为0的时候表示ASCII码,为1的时候表示自己国家的编码。
以中文GBK为例,GBK使用固定的两个字节,当解析到的字节最高位为0时,只解析当前字节作为ASCII码,当最高位为1的时候,就将下一个字节读进来一起解析为一个汉字,而不用考虑第二个字节的最高位,然后跳到第三个字节继续解析,往复如此直到解析完成。
其他国家和地区的编码系统也大致如此。
第三阶段 秦王扫六合之书同文——Unicode
现在问题来了,每个国家在设计自己国家的编码的时候基本上都只考虑了自己国家的需求,导致不同国家之间的编码互不兼容,这给不同国家之间的交流造成了很大的阻碍和困扰。
这时候就需要有人来干秦始皇干过的“车同轨、书同文”的事了,于是就出现了Unicode。Unicode为世界上所有字符设定了统一并且唯一的数字序号,这个编号范围从0x000000到0x10FFFF,包括110多万。也就是说,世界上所有国家的文字和字符都能在Unicode中找到唯一的序号,这样一来大家就有了统一编码标准。
第四阶段 小篆到简体中文——UTF-8
但是,Unicode只规定了编号,没有规定编号到二进制的映射方式。
我们先做最简单的设想:在计算机中使用固定数量的字节来存储Unicode,即直接存储所有的字符编号的二进制编码。但这样的话对于编号比较小的那些字符来讲高位全都是0,非常浪费空间,再考虑到最常用的字符编号都比较小,这么做的话对于网络传输速度和存储空间都是极大的浪费,所以我们需要一种变长的Unicode映射方式来节省空间,于是就出现了UTF-8。
UTF-8就是使用变长字节表示,每个字符使用的字节个数与其Unicode编号的大小有关,编号小的使用的字节就少,编号大的使用的字节就多,使用的字节个数从1到4个不等。这样一来存储同样多的信息需要的内存空间就便少了很多,在网络通信中获取信息的效率也会提升很多。
UTF-8的优势如此明显,所以它很快就席卷了全球,成为了大家最常用的编码。
一点补充:
UTF-8编码中,大多数中文占用的字节数是3个,相较于GBK的2个,多出了50%,这也就意味着在存储纯中文文档的时候,UTF-8编码的文件占用空间是GBK编码文件的1.5倍。
基于上面这项特性,GBK在很多纯中文系统中还是有很大的应用市场。其目的呢,就是为了节省用户的硬盘和流量
两点补充(关于java中的char):
Unicode给世界上每个字符分配了一个编号,编号范围从0x000000到0x10FFFF。编号范围在0x0000到0xFFFF之间的字符,为常用字符集,称BMP(Basic Multilingual Plane)字符。编号范围在0x10000到0x10FFFF之间的字符叫做增补字符(supplementary character)。
Unicode主要规定了编号,但没有规定如何把编号映射为二进制,UTF-16是一种编码方式,或者叫映射方式,它将编号映射为两个或四个字节,对BMP字符,它直接用两个字节表示,对于增补字符,使用四个字节,前两个字节叫高代理项(high surrogate),范围从0xD800到0xDBFF,后两个字节叫低代理项(low surrogate),范围从0xDC00到0xDFFF,UTF-16定义了一个公式,可以将编号与四字节表示进行相互转换。
Java内部采用UTF-16编码,char表示一个字符,但只能表示BMP中的字符,对于增补字符,需要使用两个char表示,一个表示高代理项,一个表示低代理项。
使用int可以表示任意一个Unicode字符,低21位表示Unicode编号,高11位设为0。整数编号在Unicode中一般称为代码点(Code Point),表示一个Unicode字符,与之相对,还有一个词代码单元(Code Unit)表示一个char。
java中char的包装类Character就封装了很多与此有关的静态方法,搞清楚这些定义有助于我们更好地理解和使用Character
漫谈计算机编码:从ASCII码到UTF-8的更多相关文章
- 三种常见的编码:ASCII码、UTF-8编码、Unicode编码等字符占领的字节数
ASCII码: 一个英文字母(不分大写和小写)占一个字节的空间.一个中文汉字占两个字节的空间. 一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制. 最小值0,最大值25 ...
- 字符串编码问题(Ascii、Unicode、UCS-2、GBK、UTF-8)
1.字符编码的发展 第一阶段:ASCII阶段,(American Standard Code for Information Interchange, "美国信息交换标准码),计算机当时只支 ...
- 所谓编码--泛谈ASCII、Unicode、UTF8、UTF16、UCS-2等编码格式
最近在看nodejs的源码,看到stream的实现里面满地都是encoding,不由想起以前看过的一篇文章--在前面的随笔里面有提到过--阮一峰老师的<字符编码笔记:ASCII,Unicode和 ...
- 字符编码(ASCII、ANSI、GB2312、UTF-8等)系统梳理
引言 在显示器上看见的文字.图片等信息在电脑里面其实并不是我们看见的样子,即使你知道所有信息都存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片.假设,你用显微镜把盘片放大,会看见盘片表面凹凸不 ...
- 中文乱码之《字符编码:ASCII,Unicode 和 UTF-8》
参考文献:字符编码笔记:ASCII,Unicode 和 UTF-8 一.ASCII 码 我们知道,计算机内部,所有信息最终都是一个二进制值.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就 ...
- 彻底搞懂字符集编码:ASCII,Unicode 和 UTF-8
一.ASCII 码 我们知道,计算机内部,所有信息最终都是一个二进制值.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte).也就是说,一个 ...
- 字符编码中ASCII、Unicode和UTF-8的区别
1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte). ...
- 字符编码(ASCII、ANSI、GB2312、UTF-8等)系统梳理(转载)
引言 在显示器上看见的文字.图片等信息在电脑里面其实并不是我们看见的样子,即使你知道所有信息都存储在硬盘里,把它拆开也看不见里面有任何东西,只有些盘片.假设,你用显微镜把盘片放大,会看见盘片表面凹凸不 ...
- 字符编码:ASCII,Unicode,UTF-8
1.ASCII码美国制定的一套字符编码,对英语字符和二进制位之间的关系,做了统一规定.ASCII码一共规定了128个字符(包括32个不能打印出来的控制符号)的编码,占用一个字节,字节的最前面1位统一为 ...
随机推荐
- Pygame小游戏练习四
@Python编程从入门到实践 Python项目练习 九.添加Play按钮 一.创建Button类 先让游戏一开始为非活动状态 # game_stats.py # --snip-- self.game ...
- django API返回中文乱码
renturn HttpResponse(json.dumps(data,ensure_ascii=False))
- Springboot使用外置tomcat的同时使用websocket通信遇到的坑
随意门:https://blog.csdn.net/qq_43323720/article/details/99660430 另外,使用了nginx的话,需要注意开放websocket支持 serve ...
- 针对Web的信息搜集
信息收集(Information Gathering),信息收集是指通过各种方式获取所需要的信息,在整个渗透测试环节中,信息搜集是整个渗透过程中最为重要的一环,信息搜集可占据整个渗透测试80%左右的工 ...
- luogu P1646 [国家集训队]happiness (最小割)
高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科 ...
- 怎样查看Nginx版本号
方法一: 使用 nginx -v nginx -v 方法二: 使用 nginx -V nginx -V 注意: nginx -V 显示的是: 版本号 / 编译器版本 / 配置参数
- hdu 3500 还是搜索
这道题目由于每走一步的时候毛毛球是可以变换的 换言之 主体不唯一 所以这里搜索的设计有变化 再就是几个回溯的过程要注意.,. 小心使得万年船 #include <iostream> #i ...
- 浅谈hashcode
哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: 1 public native int hashCode(); 根据 ...
- 批量Insert
oracle INSERT ALL ,) ,) ,) FROM DUAL
- 如何使用jMeter发送两个逻辑上相关的HTTP请求
在前一篇文章使用jMeter构造大量并发的随机HTTP请求里我通过jMeter构造了大量的HTTP GET并发请求,对服务器产生了大量读操作. 现在我有另一个需求场景:假设我开发了一个创建Servic ...