各种编码区别及内存映射

整件事起因是一个程序(这条死咸鱼还欠着两篇文章没有写)

室友问道为啥一个

1
2
String str = "中";
str.getBytes().length;

结果是3,而不是我们当时常见的一个中文对应2字节

本质上的原因是因为他编辑器用了utf-8编码

后来又看到这么一段话

“计算机内存中,统一使用Unicode编码,需要保存或者传输时,转换成UTF8编码。”

然后我就懵逼了

对于编码方面的知识我的理解是混乱的,因此写篇blog理清一下思路

正文

1. 编码规范的发展

常见编码有ASCIIGBKUnicodeUTF-8GB2312等等等

所以有什么区别呢?

推荐一篇浅显易懂的文章

Unicode 和 UTF-8 有何区别? - 回答作者: 于洋

本身答主也是转发的,并不清楚原文最初发表在哪

所以,总结一下

  • ASCII (American Standard Code for Information Interchange)

    学过计算机的人都知道 ASCII 码,总共有 128 个,用一个字节的低 7 位表示,0~31 是控制字符如换行回车删除等;32~126 是打印字符,可以通过键盘输入并且能够显示出来。

  • Unicode (Universal Coded)

    每个字符占两字节,解决不同国家间字符编码不相容的问题。但这样的话对于多英文字符的其大小就会变大。

  • ISO-8859-1

    128 个字符显然是不够用的,于是 ISO 组织在 ASCII 码基础上又制定了一些列标准用来扩展 ASCII 编码,它们是 ISO-8859-1~ISO-8859-15,其中 ISO-8859-1 涵盖了大多数西欧语言字符,所有应用的最广泛。ISO-8859-1 仍然是单字节编码,它总共能表示 256 个字符。

  • GB2312

    它的全称是《信息交换用汉字编码字符集 基本集》,它是双字节编码,总的编码范围是 A1-F7,其中从 A1-A9 是符号区,总共包含 682 个符号,从 B0-F7 是汉字区,包含 6763 个汉字。

  • GBK (Guojia Biaozhun Kuozhan)

    全称叫《汉字内码扩展规范》,是国家技术监督局为 windows95 所制定的新的汉字内码规范,它的出现是为了扩展 GB2312,加入更多的汉字,它的编码范围是 8140~FEFE(去掉 XX7F)总共有 23940 个码位,它能表示 21003 个汉字,它的编码是和 GB2312 兼容的,也就是说用 GB2312 编码的汉字可以用 GBK 来解码,并且不会有乱码。

  • GB18030

    全称是《信息交换用汉字编码字符集》,是我国的强制标准,它可能是单字节、双字节或者四字节编码,它的编码与 GB2312 编码兼容,这个虽然是国家标准,但是实际应用系统中使用的并不广泛。

  • UTF-16

    说到 UTF 必须要提到 Unicode(Universal Code 统一码),ISO 试图想创建一个全新的超语言字典,世界上所有的语言都可以通过这本字典来相互翻译。可想而知这个字典是多么的复杂,关于 Unicode 的详细规范可以参考相应文档。Unicode 是 Java 和 XML 的基础,下面详细介绍 Unicode 在计算机中的存储形式。

    UTF-16 具体定义了 Unicode 字符在计算机中存取方法。UTF-16 用两个字节来表示 Unicode 转化格式,这个是定长的表示方法,不论什么字符都可以用两个字节表示,两个字节是 16 个 bit,所以叫 UTF-16。UTF-16 表示字符非常方便,每两个字节表示一个字符,这个在字符串操作时就大大简化了操作,这也是 Java 以 UTF-16 作为内存的字符存储格式的一个很重要的原因。

  • UTF-8

    UTF-16 统一采用两个字节表示一个字符,虽然在表示上非常简单方便,但是也有其缺点,有很大一部分字符用一个字节就可以表示的现在要两个字节表示,存储空间放大了一倍,在现在的网络带宽还非常有限的今天,这样会增大网络传输的流量,而且也没必要。而 UTF-8 采用了一种变长技术,每个编码区域有不同的字码长度。不同类型的字符可以是由 1~6 个字节组成。

    UTF-8 有以下编码规则:

  1. 如果一个字节,最高位(第 8 位)为 0,表示这是一个 ASCII 字符(00 - 7F)。可见,所有 ASCII 编码已经是 UTF-8 了。
  2. 如果一个字节,以 11 开头,连续的 1 的个数暗示这个字符的字节数,例如:110xxxxx 代表它是双字节 UTF-8 字符的首字节。
  3. 如果一个字节,以 10 开始,表示它不是首字节,需要向前查找才能得到当前字符的首字节。

在搜索资料过程看到一个解释得非常清楚的文章,介绍在Java中的中文编码问题,也把编码本身说得很清晰了。

https://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/

二、问题

但其实,我当时最不理解的是看到的一句话

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码

感觉需要理解的是,Unicode是一种字符集,而UTF-8是一种字符编码

可以看一下这篇博文http://cenalulu.github.io/linux/character-encoding/

UTF-8跟Unicode之间通过一定关系转化,而UTF-8并没有涵盖整个Unicode字库

感觉目前很多说法都有问题,说某个文件用了Unicode编码

例如在记事本中,然而如果我用Unicode保存,在别的编辑器(vscode, sublime)上显示出来的是UTF-16 LE

Unicode是一种字符集,并不是一种字符编码,这样理解才对

×

赞助gif换电脑、吃双皮奶(逃

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 正文
    1. 1.0.1. 1. 编码规范的发展
      1. 1.0.1.0.0.1. 本身答主也是转发的,并不清楚原文最初发表在哪
  • 1.0.2. 二、问题
  • ,