zoukankan      html  css  js  c++  java
  • Unicode、UTF8、GB2312、ANSI

    来源:https://blog.csdn.net/osanwenyu/article/details/48439461

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                

                        本文链接:https://blog.csdn.net/oSanWenYu/article/details/48439461                

                                                                                  

    一、前言

    汉字编码是让人比较头疼的一块,最近下定决定把他搞懂。网上翻了个遍,讲得详细透彻的让人头疼看不下去,讲得通俗的不够详细,只言片语。更有甚者开篇即讲Unicode是啥,多少个字符,GB2312巴拉巴拉,多少个汉字,全然不讲应用场景,不理知识接受的先后,遂结合翻看过的几篇写一写心得。

    二、字符编码的发展

    ASCII

    --> 拓展字符集

    -->GB2312(中国大陆) 

    -->GBK 

    --> unicode

    1.ASCII 

    最早的时候计算机只在美国使用,人民解决英文与二进制的映射关系,发明了ASCII编码,将所有大小写英文字母以及常用的英文标定符号编进去。还有一些并不代表文字意义但又经常要表达的操作也加了进去,这就是控制字符,如换行、回车、制表符等等。这时发现所有的字符都编进去了,才占用了127个,每个字符占用一个字节,这是一套完美的编码方式。

    2.拓展字符集

    后来科技发展,计算机在世界各国普及开来,英语地区还好,直接能显示英文,非英语地区就没那么好运了。为此程序员们为自己的母语开发了自己文字与二进制的映射关系(主要是拉丁系文字的国家),从128一直占用到字节的最后一个255,这拓展的128个加上原有的128个,一共256个九叫做ASCII拓展字符集,又称IBM拓展字符集。

    3.本地化(GB2312、BIG5、Shift JIS...)

    再后来非拉丁系国家一看不行啊,我也要搞自己的字符集,于是百花齐放的时代来了,由于一个字节的已经被占满了,各国都采用2个字节代表自己的一个文字,如中国将第一个字节的AI~F7,第二个字节的00~FF合起来表示一个汉字,来代表7000多个汉字,直接抛弃不兼容拓展字符集,并将此字符集称为GB2312。后来又加入一些少数民族的文字、繁体字,演化出GBK。

    4.Unicode一统天下

    各国的字符编码都有自己的一套编码方法,彼此之间并不兼容,这显然不是最好的解决方案。为此ISO国际标准化组织提出unicode方案,以2个字节表示一个字符:

    0000-007F:原基本ASCII字符集中的字符
    0080-00FF:原拓展字符集中的字符
    ......
    0600-06FF:阿拉伯文
    ......

          4E00-9FBF:CJK 统一表意符号(包含中文字符)

    ......

    将ASCII编码中的前128个字符保持不变,即第一个字节保持不变,后一个字节用0填充,如"A"的unicode为 0X0041,其他文字依次排在后面的空余位置,兼容世界上所有的字符!

    至此字符编码演化到了最终形态。unicode与各种本地化编码共存,至于为什么共存,有太多原因,如ASCII,本来只需要1个字节表示1个"A",现在要用2个字节,容量足足翻了一番。至于GB2312,就如同国际上有了W-CDMA中国还要搞TD-CDMA一样。

    唉?等等,你说UTF8?  

    三、unicode 与 UTF8

    unicode在计算机内部(或者说单机)使用时,使用unicode是没问题的,如一个记事本,以unicode方式保存,操作系统会在记事本的开头标记一下FFEF或FEFF,以此说明是采用双字节的unicode编码,因内存读写极少出错,所以基本不会发生丢字节的情况。此时的编码即UTF-16。

    那传输(联网)时呢?

    考虑一个现实问题:假设你是一台计算机(小端),需要将另一台计算机(小端)传过来的unicode数据(你0x4f60   好0x597d   吗0x5417)转为字符并显示在屏幕上。

    第一次,你遇到一个0x4F60,好办!显示器!给我显示”你“!

    第二次,0x7d丢失,你遇到一个0x5917,也好办,”夗“! 

    第三次,你遇到一个0x5400,“吀”

    显示结果:你夗吀  (什么鬼!)

    可见,unicode在传输方面还是有缺陷的,因为每个字符看着都像是独立的,跟前后没有什么依赖关系,也没有相关标识,一旦少了一个字节,后面的所有内容都乱码了。

    解决方法也显而易见,就是每个字节都标识一下,UTF-8应运而生。

    四、unicode与UTF8的转换

    UTF8的第一个字节的前4位用以标识本次传输的字符占用多少个字节,如1110 xxxx 标识占用3个字节。

    剩余的字节都采用开头为10的方式,如10xx xxxx。

    比如“ 直 ”, unicode编码: 76f4 ,   相应二进制   0111 0110 1111 0100

    因为汉字的unicode固定是2个字节,而转成utf8则是固定3个字节。

    1110 ____,  10__ ____, 10__ ____

    将“ 直” 0111 0110 1111 0100 连续填入:

    二进制 : 1110 0111,  1001 1011, 1011 0100, ,十六进制 : e79b94,此为UTF-8

    五、被滥用的UTF-8

    UTF-8一开始只用于网络传输,并不作为本地存储形式,后来程序员们因为懒、麻烦,不会引起其他问题等种种不啦不啦原因,直接将UTF-8用于存储。

    如何知道文件用的是什么方式编码的呢?

    二进制打开文件,开头字节能区分。

    开头字节

    Charset/encoding

    EF BB BF

    UTF-8

    FE FF

    UTF-16/UCS-2, little endian

    FF FE

    UTF-16/UCS-2, big endian

    FF FE 00 00

    UTF-32/UCS-4, little endian.

    00 00 FE FF

    UTF-32/UCS-4, big-endian.

    开头字节 Charset/encoding
    ANSI(中文是GB2312)
       
       

    六、要点

    unicode能表示所有的字符,任何其他的编码方式都是针对特定字符的。

    unicode在本地的形式是UTF-8,UTF-16,UTF-32,网络传输形式只能是UTF-8

    开头字节能区分编码方式

  • 相关阅读:
    苹果手机 iframe 无法滚动bug
    网页实现文件下载的一些方法
    Document对象中的一些重要的属性和方法(笔记)
    window对象中的一些重要的属性和方法(笔记)
    JS中的继承
    利用XMLHttpRequest(XHR)对象实现与web服务器通信
    JS对象中的原型
    JS中this的指向
    JS中的作用域和闭包
    HTML5新增的本地存储功能(笔记)
  • 原文地址:https://www.cnblogs.com/MCSFX/p/11511100.html
Copyright © 2011-2022 走看看