第48篇 字符编码探密--ASCII,UTF8,GBK,Unicode
原文地址:http://blog.laofu.online/2017/08/22/encode-string/
ASCII 的由来
在计算机的“原始社会”,有人想把日常的使用的语言使用计算机来表示, 我们知道在计算机的世界里面,只有0和1,为了解决尽量多的去表示字符,最终他们决定用8位0和1(一个字节)来表示字符,并且规定当机器读到这几个数据的时候,做出动作或者打印出指定的字符:
遇上0001 , 终端就换行; 遇上0000 , 终端就向人们嘟嘟叫; 遇上 , 打印机就打印反白的字,或者终端就用彩色显示字母。
这样就形成了最早期的ASCII码表,并把小于32的字符称为“控制字符”,剩下的继续进行编写,一直到127个字符,这样一套完整的字符方案就完成了,终于可以把文字搬到计算机中了。
当大家都在兴奋的可以在电脑的阅读的文章的时候,新的问题又出现了,随着计算机的普及,很多国家都使用了计算机,原来的ASCII码在使用英语的国家可以无障碍的使用,但到了其它国家就无法满足要求了,所以他们决定对后面没有用到的编码(128-255)表示自己国家的语言,并加上了其它的相关的符号,直到编码空间被全部用完,从128-255的字符集称为“ASCII的扩展字符集”。
汉字怎么办?
等到中国人使用电脑的时候,发现已经没有编码供我们来存储对应的汉字了,连扩展的空间都已经被全部占满了。所以我们的前辈们用自己的智慧创造性提出了新的编码格式:
. 去除127之外的乱七八糟的字符串和符号 . 如果一个字节且小于127号的字符,与原ASCII码意义相同 . 如果有两个同时大于127的字符则表示一个汉字,所以就会有一个字符会占用两个字节的说法
由于汉字占用两个字节,为了方便区别,我们把前面的字节称为“高位”(从161-247),后面的为“低位”(161-254),这样的一个搭配能表示出大概7000多个数字, 这个编码把所有用到的数字,符号,标点等等都编写进去,其中也有包括对ASCII码的重写,这样就会有我们常说的全角和半角的符号之分。这样的编码格式就是我们常说的“GB2312”
博大精深的文化带来的编码麻烦
当我们庆幸我们的汉字可以在计算中进行传递时,却发现GB2312编码小小的内存空间无法表示“博大精深文化” 需求,很多生僻字无法打印。所以不得不对现有的编码格式就行扩容,在剩余高位和低位的空间中寻找还没有使用的编码,但后来发现还是不够用,因为我们还有繁体字。
经过几次折腾,最终决定放弃对低位的限制,不再要求低位是大于127的值,一旦发现高位是大于127的就认为是汉字,这样又多了大概20000个汉字的表示,这种扩展的编码格式称为:GBK2312
再后来我们发现光有汉字是无法把“中国的文字” 全部表示出来,我们还要表示其它民族的文字,所以又对原来的编码格式进行扩展,最终形成编码:GB18030
Unicode的诞生
随着计算机的普及,世界很多国家和很多民族都使用了计算机,各种编码格式也越来越多。随着相互之间的文字交流也越来越频繁,编码格式是成为了主要的障碍,是时候是时候需要一个更为兼容性强大的的编码格式来一统天下,这个编码就是Unicode,创建它的是就是ISO(国际标谁化组织)。ISO当然解决这个问题也比较简单粗暴:
. 废除所有地区性的编码 . 重新制定一个能够包含地球上所有的编码
在Unicode的制定的时候,硬件已经不再那么的昂贵,所以就大气的把原来的使用一个字节表示(8位),改用成两个字符(16位)表示,其它的字符统一编码,这样理论上一共最多可以表示2^16(即65536)个字符,基本满足各种语言的使用。实际上当前版本的统一码并未完全使用这16位编码,而是保留了大量空间以作为特殊使用或将来扩展。这种大气的方式,虽然统一的编码方式,但也同样带来了问题,由于扩展的字节数,使用原来能用一个字节表示的字母和半角字符的高位都是0,存储空间比原来多了一倍。同样Unincode中,所有的字符都是都是两个字节 而汉字也由原来的两个字符转成了一个字符 –(更多的实现方式不属于此文的讨论之内)
这里要注意字符与字节的区别,在ASCII码的代码,一个字节是8位,用一个字节来表示一个字符,而汉字用两个字节来表示,所以有汉字可以作为两个字符。 而在Unicode时代,一个字节还是8位,但是所有的字符表示都是用两个字节,所以汉字也就算成一个字符
上述16位统一码字符构成基本多文种平面。最新(但未实际广泛使用)的统一码版本定义了16个辅助平面,两者合起来至少需要占据21位的编码空间,比3字节略少。但事实上辅助平面字符仍然占用4字节编码空间,与UCS-4保持一致。未来版本会扩充到ISO -1实现级别3,即涵盖UCS-4的所有字符。UCS-4是一个更大的尚未填充完全的31位字符集,加上恒为0的首位,共需占据32位,即4字节。理论上最多能表示2^31个字符,完全可以涵盖一切语言所用的符号。
相关资料:Unicode字符平面映射
半角字符“A”的表示方法: ASCII码: Unicode编码: 汉字“付”的表示方法 GBK编码: Unicode编码:
UTF8的出现
伴随着Unicode的缺点的出现,特别是到互联网的出现,为解决unicode如何在网络上传输的问题,可谓各种实现方法都出现了,具有代表性的就是UTF8和UTF16。这里强调:他们的关系是UTF8和UTF16是Unicode的一种实现方式。
那UTF8又是如何表示字符的呢? UTF8的最大的特点是可伸缩性,具体的编码规则:
. 对于一个单字节字符,而且首位为0 ,其余的用Unicode补齐。所以对于ASCII内的字符,ASCII的编码与UTF8相同。 . 对于n字节的字符,第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
还是以“付”为例:
汉字“付”的表示方法 GBK编码: Unicode编码: UTF-8编码:
在读取UTF编码的时候,我们只需要读取前面几位有几个1 ,就可以清楚的知道,当前字符占用了几个字节。
至于编码的转换,如果理解了原理就很简单了,如果有机会我会写出如何手动去转换字符编码 –(如果我还有动力的写下篇的话~)
.net代码实现一个字符编码转换,这里转出来是二进制的数据,其它格式可以自己扩展:
public static void Main(string[] args)
{
ConvertEncode("Unicode", "GBK", "付");
Console.Read();
}
private static void ConvertEncode(string tarEncode, string desEncode, string content, string defaultEncode = "Unicode")
{
var byteArr = Encoding.GetEncoding(defaultEncode).GetBytes(content);
var str = Encoding.Convert(Encoding.GetEncoding(tarEncode), Encoding.GetEncoding(desEncode), byteArr);
foreach (var b in str)
{
Console.Write(Convert.ToString(b, ));
}
}
【参考资料】
第48篇 字符编码探密--ASCII,UTF8,GBK,Unicode的更多相关文章
- 字符编码ANSI和ASCII区别、Unicode和UTF-8区别
ANSI码ANSI编码是一种对ASCII码的拓展:ANSI编码用0x00~0x7f (即十进制下的0到127)范围的1 个字节来表示 1 个英文字符,超出一个字节的 0x80~0xFFFF 范围来表示 ...
- Android中检测字符编码(GB2312,ASCII,UTF8,UNICODE,TOTAL——ENCODINGS)方法(一)
package com.android.filebrowser; import java.io.*; import java.net.*; public class FileEncodingD ...
- Android中检測字符编码(GB2312,ASCII,UTF8,UNICODE,TOTAL——ENCODINGS)方法(一)
package com.android.filebrowser; import java.io.*; import java.net.*; public class FileEncodingD ...
- Android中检测字符编码(GB2312,ASCII,UTF8,UNICODE,TOTAL——ENCODINGS)方法(二)
Intent intent = getIntent(); String contentUri = null; Uri uri =null; if (in ...
- 字符编码之间的转换 utf-8 , gbk等,(解决中文字符串乱码)
目录 1.背景. 2.编码的理解 3.编码之间的相互转化 4. str类型说明 5. 可以使用的编码类型 6.参考文章 1.背景 Python中与其他程序进行交互时,如果存在字符串交互,特别是字符串中 ...
- 字符编码笔记:ASCII,Unicode和UT…
字符编码笔记:ASCII,Unicode和UTF-8 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才 ...
- 字符编码笔记:ASCII,Unicode和UTF-8(转)
字符编码笔记:ASCII,Unicode和UTF-8 作者: 阮一峰 日期: 2007年10月28日 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个 ...
- 字符编码简介:ASCII,Unicode,UTF-8,GB2312
字符编码简介:ASCII,Unicode,UTF-8,GB2312 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和 1两种状态,因 ...
- [转帖]字符编码笔记:ASCII,Unicode 和 UTF-8
字符编码笔记:ASCII,Unicode 和 UTF-8 http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 转帖 ...
随机推荐
- 使用C#创建SQLite桌面应用程序
本文属于原创,转载请注明出处,谢谢! 一.开发环境 操作系统:Windows 10 X64 开发环境:VS2015 编程语言:C# .NET版本:.NET Framework 4.0 目标平台:X86 ...
- 基于pytorch实现word2vec
一.介绍 word2vec是Google于2013年推出的开源的获取词向量word2vec的工具包.它包括了一组用于word embedding的模型,这些模型通常都是用浅层(两层)神经网络训练词向量 ...
- multipath多路径实验01-构建iscsi模拟环境
multipath多路径实验01-构建iscsi模拟环境 前几天跟同事网上闲聊技术,吐槽之前自己没有配置过多路径的经历,虽然多路径的配置过程很简单,职责划分也应是主机或存储工程师来搞定,DBA只需要直 ...
- xdu_1165:均值滤波
题目: Problem A 均值滤波问题描述图像中的噪声在空间上的自相关很低,因此往往可以用均值滤波加以削弱.具体来说,对于每个像素点P(x; y),我们选出所有距P 的Manhattan 距离不超过 ...
- 让 Python 带你进入开源的世界——Git 从入门到与他人协作开发
让 Python 带你进入开源的世界--Git 从入门到与他人协作开发 我认为开源社区中有很多优秀的资源,并且可以帮助进阶中的程序员提高编程能力和水平.所以,我发起了<HelloGitHub&g ...
- Java IO 之 BIO、NIO、AIO
1.BIO.NIO.AIO解释 Java BIO : 同步并阻塞 (Blocking IO) 一个连接一个线程 即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不 ...
- MySQL系列(三)---索引
MySQL系列(三)---索引 前言:如果有疏忽或理解不当的地方,请指正. 目录 MySQL系列(一):基础知识大总结 MySQL系列(二):MySQL事务 MySQL系列(三):索引 什么是索引 如 ...
- 使用gitLab 或 github 关联本地仓库
要先在git里面注册自己的邮箱 然后: git commit -m 是为本次提交命名 刷新gitLab 发现更新了
- html、js、django处理日期问题
在html中使用日期控件,利用ngmodel将输入的值传到js里: <input type="date" ng-model="timeOps.test.a_time ...
- 带你快速进入.net core的世界
[申明]:本人.NET Core小白.Linux小白.MySql小白.nginx小白.而今天要说是让你精通Linux ... 的开机与关机.nginx安装与部署.Core的Hello World .. ...