字符编码(UTF-8,16,32 和GBK和ASCLL码)

发布于:2025-06-21 ⋅ 阅读:(18) ⋅ 点赞:(0)

 迅速通读本文:

        计算机一开始是美国人弄出来的,我们都知道二进制可以表示很多数字,但是无法直接表示字符对吧,出现了一个需求要求表示字母和一些常见的符合,于是想到一个办法,类似于字典一样或者说map,用一个值去对应一个个字符,所以这个“字典”就是ascall码值,而且对应的一个个字符都是1个字节(8位)来存放这些字符。

    随着时间的发展啊对吧,不同国家有不同的语言需求,所以原来的单纯的ascll码值这个字典以及不满足于人们需求。就有了各种需求,中国人弄了GBK(编码存了大量的简体 甚至生僻字等等满足国内的需求),日本人弄了一个Shift_JIS编码,台湾也有自己的。但是后来国家与国家之间的人们有交流需求,不同的编码编写的文件,用不对应的编码方式来打开会出现乱码啊。 

    所以为了统一标准 国际上搞了一本字典,记录这个世界上所有的语言,以及符号等等这样大家都统一了,也就是Unicode,它相当于一个指导,还不是编码值,也就是定义了一系列的变化对应的值呢还没实现,因为前面我们说了类似于“字典”的模式,键跟值是要一一对应的,那么谁来实现了这个需求呢?  目前实现它的有变长字符UTF-8, 定长的:utf-16 ,UTF-32。

一、ASCII:计算机的 "基础英语词汇表"

   1. 诞生背景:让计算机认识字母


   20 世纪 60 年代,计算机只能处理 0 和 1,但人类需要输入字母。于是美国人搞了个「英语专用翻译手册」——ASCII 码。它规定:

  • A = 65(二进制01000001
  • a = 97(二进制01100001
  • 0 = 48(二进制00110000

    意思就是:ascll码值跟这个字符一一对应 这样就可以实现把字符存储到计算机中啦。

  2. 存储大小:1 字节的 "小盒子"


ASCII 用 1 字节(8 位)存储一个字符,总共能表示 128 个符号(2^7,最高位固定为 0)。比如

  • 'A'的二进制是01000001,存进计算机就是这 8 位。

3. 致命缺陷:只能装 "英语单词"

    实际上不仅仅英文单词这里只是简单的阐述实际上ASCLL码值还能表示一些其他的字符,但是当然很难满足我们其他国家的人啊,比如我们用汉语
 简单来说ASCII 就像一本只有 26 个英文字母 + 数字 + 标点的字典:

  • 想存中文?没位置!
  • 想存俄语字母?没位置!
  • 甚至想存笑脸😀?更没位置!
灵魂画图 1:ASCII 的 "小盒子"

+--------+
| 01000001 |  →  存'A'
+--------+
  1字节空间

(每个盒子只能装 1 个英文字母,多了装不下)

二、Unicode:给全世界字符 "分配身份证"

1. 为什么需要 Unicode?


20 世纪 90 年代,互联网普及,各国语言冲突爆发:

  • 中文用 GB2312,日文用 Shift_JIS,不同编码文件互开就是乱码!
  • 程序员吐槽:"我写个程序,存中文用 GBK,存日文得换编码,太麻烦了!"

2. Unicode:全球字符的 "统一身份证号"


Unicode 像一本全球字典,给每个字符分配唯一编号(码点):

  • 'A' → U+0041
  • '中' → U+4E2D
  • 😀 → U+1F600

3. 注意:Unicode≠编码!
      Unicode 只是 "字符编号表",就像字典里 "中" 字的编号是 4E2D,但怎么把这个编号存进计算机?需要 UTF 家族来 "翻译"。

三、UTF-8:最聪明的 "变长翻译官"

    1. 为什么叫 "变长"?


UTF-8 的核心思路:

  • 英文字母用 1 字节存(兼容 ASCII)
  • 欧洲字母用 2 字节存
  • 中文 / 日文用 3 字节存
  • 罕见符号(如😀)用 4 字节存

2. 编码规则:用 "前缀" 标记字节数


UTF-8 的每个字节开头有特殊前缀,像快递盒上的 "尺寸标签":

  • 1 字节字符:前缀0 → 存 ASCII 字符
  • 2 字节字符:前缀110+10
  • 3 字节字符:前缀1110+10+10
  • 4 字节字符:前缀11110+10+10+10

灵魂画图 2:UTF-8 的 "快递盒"

+--------+  1字节盒(装英文):前缀0
| 0xxxxxxx |  

+--------+  +--------+  2字节盒(装欧洲字符):
| 110xxxxx |  | 10xxxxxx |  

+--------+  +--------+  +--------+  3字节盒(装中文):
| 1110xxxx |  | 10xxxxxx |  | 10xxxxxx |  

+--------+  +--------+  +--------+  +--------+  4字节盒(装emoji):
| 11110xxx |  | 10xxxxxx |  | 10xxxxxx |  | 10xxxxxx |

3. 实例:' 中 ' 字的 UTF-8 编码
'中'的 Unicode 码点是 U+4E2D(二进制100111000101101
用 3 字节 UTF-8 存储:

  1. 把二进制码点填入 3 字节的 "数据位":

    plaintext

    1110xxxx 10xxxxxx 10xxxxxx  
    ↓        ↓        ↓  
    11100100 10111000 10101101  
    
  2. 转成十六进制:0xE4 0xB8 0xAD,共 3 字节。
四、UTF-16 和 UTF-32:两种 "极端" 的翻译方式

1. UTF-32:简单粗暴的 "定长盒子"

  • 每个字符固定占 4 字节,不管是英文还是中文
  • 优点:计算字符位置简单(第 n 个字符在 4*n 字节处)
  • 缺点:存英文太浪费空间!'A'存成00000041,4 字节!

灵魂画图 3:UTF-32 的 "傻大盒子"

plaintext

+--------+--------+--------+--------+
| 00000041 |        |        |        |  →  存'A',浪费3字节
+--------+--------+--------+--------+

2. UTF-16:折中方案的 "中等盒子"

  • 常用字符占 2 字节,罕见字符占 4 字节
  • Windows 和 Java 的默认编码,平衡空间和效率
  • 例子:'A'存 2 字节,'中'存 2 字节,😀存 4 字节
  • 3. 为什么会有他们俩 以及用在什么地方
  •  计算机算机处理 UTF - 8 编码的字符时,需要根据编码规则来解析字符,确定每个字符占用的字节数等,这比处理固定长度编码(如 UTF - 32)要复杂一些,会消耗更多的 CPU 时间和计算资源。例如,在对 UTF - 8 编码的字符串进行搜索、排序等操作时,计算机需要花费更多时间来处理。
  •    他们俩一般用再---》比如嵌入式开发的时候。

五、为什么 UTF-8 成为互联网 "顶流"?

1. 三大优势吊打其他编码:

  • 兼容 ASCII:英文文件用 UTF-8 存和 ASCII 一样大,无缝衔接老程序
  • 节省空间:中文占 3 字节,比 UTF-32 的 4 字节省 25%
  • 抗错误能力强:某个字节出错,只影响当前字符,不会破坏后续内容

2. 数据证明:

  • 全球 85% 的网页用 UTF-8(2023 年统计)
  • GitHub、Linux、HTML5 默认编码都是 UTF-8

六、编码那些坑:为什么会出现 "乱码"?

1. 经典场景:用错误编码打开文件
比如:

  • 一个 UTF-8 编码的中文文件,用 GBK 编码打开
  • 计算机误解了字节组合:

    plaintext

    UTF-8的"中"是E4 B8 AD(3字节)  
    GBK把E4 B8当成一个字符,AD当成另一个字符  
    结果显示为乱码"涓"
    

灵魂画图 4:乱码的真相

plaintext

正确翻译(UTF-8):        错误翻译(GBK):
+---+---+---+          +---+---+---+
|E4|B8|AD|  → '中'     |E4|B8|AD|  → 乱码字符
+---+---+---+          +---+---+---+

2. 程序员必知:编码转换的陷阱

  • 从 UTF-8 转 UTF-16:简单,按规则转换
  • 从 GBK 转 UTF-8:可能丢失字符(GBK 只包含简体中文,不包含 emoji 等)

七、总结:编码的本质是 "翻译协议"

  • ASCII:计算机的英语入门教材,1 字节存英文
  • Unicode:全球字符的字典,给每个字符发 "身份证"
  • UTF-8:最聪明的翻译官,用不同大小的盒子存字符,兼容英文又省空间
  • 乱码:翻译官拿错了字典,把 "中文" 翻译成了 "火星文"

最后灵魂拷问:
为什么😀在 UTF-8 里占 4 字节?
因为它的 Unicode 码点 U+1F600 超过了 3 字节能表示的范围(3 字节最大到 U+10FFFF,而 U+1F600 在 U+100000 以上),只能用 4 字节存啦!

附录:常见字符编码对比表
字符 Unicode 码点 UTF-8 (字节) UTF-16 (字节) UTF-32 (字节)
'A' U+0041 0x41 (1) 0x0041 (2) 0x00000041 (4)
' 中' U+4E2D 0xE4B8AD (3) 0x4E2D (2) 0x00004E2D (4)
'€'(欧元符号) U+20AC 0xE282AC (3) 0x20AC (2) 0x000020AC (4)
'😀' U+1F600 0xF09F9880 (4) 0xD83DDE00 (4) 0x0001F600 (4)

  拓展:

   a. 为什么既然utf8都这么方便了既可以兼容ascll码值还是变长的会识别字符选择合适的内存大小存储字符还要存在utf-16和utf-32?

      utf-8,这个8呢是指它存最小内存单位是8字符也就是简单的字符(包括ascll码值中的)它会选择一个字符的,对于复杂一点的。。中文3字节等等 

  你发现没有很神奇对吧!它会自动耶好腻害。那你就失算了,你说帮你自动识别了这个过程要不要消耗资源(特别是时间资源,肯定会调算法啊 排序啊等等) 那它这样影响效率了啊,那怎么办

   所以就有定长的啦:一个是utf-16  16位 2个字节而已(最小2个字节定长的)它的好处就是大多字符编码都是2字节这样使用效率会好很多,但是一点点缺点就是可能不够用啊 才两个字节,这个时间有很多语言它可能表示不了。  

  所以为了进一步满足需求语言足够用的需求那就使用了utf-32,那缺点是啥内存太大了呗,比如我存一个字符'A'上来好家伙就4字节了。

 用处

    你猜? 嵌入式方面这种偏向机械的内部编码会用谁,当然是为了效率肯定用utf-16.

    utf-8 是很通用的所以啊大多会呗用来网站啊,操作系统,一些工具啊 编译器等等比如你的IDEA,VS2020啊,等等

   gbk

   国内的GBK为什么还在用不改用utf-8,其实就跟c++要兼容c语言一样,当初出gdb的时候国内很多系统啊都是用了gdb啊。 目前也有一些操作系统专门位gdb编码啊比如windows xp 这个你可能听过默认中午编码就是gdb。

   它其实设计的很巧妙的,2个字节存中文,内存上大大的优化很高的,但是吧。。。时代在召唤,必然迈向国际化呗。   

      


网站公告

今日签到

点亮在社区的每一天
去签到