理解字符编码

简介: 理解字符编码

写代码这么久,突然发现并不了解字符编码。我们每天写下的代码,或者文件,在计算机中究竟是怎样的存在?我们都知道,计算机能够认识的只有 01。所以,不论任何数据,最终在计算机中只是 01 的排列组合。那么计算机时如何识别这些排列组合的呢?这就需要 字符编码(Character encoding)了。简单的说,就是按照一定的规则将信息与其对应的 01 的排列组合对应起来,这样计算机就可以根据字符编码识别出硬盘中的排列组合所代表的真实信息了。常见的 ASCIIUTF-8GBK 等等,都是典型的字符编码。计算机到底是如何辨别这些字符编码的,就要看一下具体的字符编码原理。


ASCII


ASCII(American Standard Code for Information Interchange,美国信息交换标准代码),是基于拉丁字母的一套电脑编码系统。注意最后两个字母是 II,而不是罗马数字 2。ASCII 是由美国国家标准协会制定的,标准的单字节字符编码方案,用于基本文本的数据。起源于 50 年代后期,在 1967 年定案。它最初是美国国家标准,供不同计算机在相互通信时用作共同遵守的西文字符编码标准,它已被国际标准化组织定为国际标准,称为 ISO 646 标准。适用于所有拉丁文字字母。


标准 ASCII 码使用单字符,即 8 个二进制位表示字符。第一位统一定为 0,实际使用后面 7 位来表示,所以 ASCII 码一共规定了 128 个字符的编码,包括所有的大小写字母,数字 0 到 9,标点符号以及一些特殊控制字符。


标准 ASCII 码表如下:

image.png

ASCII 是美国标准,并不能满足其他语言的需求。例如英镑符号,中文汉字等等。西方一些国家使用 8 个二进制位来表示字符,最多可以表示 256 个字符。显然,对于汉字而言,一个字符不可能满足需求。


ANSI


为了扩充 ASCII 编码,以用于显示本国的语言,不同的国家和地区制定了不同的标准,由此产生了 GB2312 , BIG5 , JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码,又称为 MBCS(Muilti-Bytes Charecter Set,多字节字符集)。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码,所以在中文 windows下要转码成 gb2312 , gbk 只需要把文本保存为 ANSI 编码 即可。不同的 ANSI 编码并不兼容,同一个二进制值在不同的编码体系中可能代表不同的字,这就导致了 Unicode 的诞生。在介绍 Unicode 之前,简单看一下 ANSI 中的中文编码。


GB2313

GB2312 也是 ANSI 编码里的一种,对 ANSI 编码最初始的 ASCII 编码进行扩充,为了满足国内在计算机中使用汉字的需要,中国国家标准总局发布了一系列的汉字字符集国家标准编码,统称为 GB码 ,或国标码。其中最有影响的是于 1980 年发布的《信息交换用汉字编码字符集 基本集》,标准号为 GB 2312-1980 ,因其使用非常普遍,也常被通称为国标码。GB2312 编码通行于我国内地;新加坡等地也采用此编码。几乎所有的中文系统和国际化的软件都支持 GB 2312


GB2312 是一个简体中文字符集,由 6763 个常用汉字和 682 个全角的非汉字字符组成。其中汉字根据使用的频率分为两级。一级汉字 3755 个,二级汉字 3008 个。


GBK

GB2312 的出现,基本满足了汉字的计算机处理需要,但是对于人名,古汉语等方面的罕用字,GB2312 不能处理,这就导致了 GBK 的出现。


GBK 采用双字节表示,总体编码范围为 8140-FEFE ,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 xx7F 一条线。总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。


Unicode


ANSI 编码的缺点很明显,同一个编码值,在不同的编码体系中代表着不同的字符,很容易造成乱码。如果有一种编码,将世界上所有的符号都融入其中,每个符号都有对应的编码值,这样就不存在乱码问题了。这就是 Unicode 编码。


Unicode 编码是一个很大的集合,现在的规模可以容纳 100 多万个符号,每个符号的编码都不一样。其实 Unicode 并不是真正意义上的字符编码,它只是一个字符集,规定了符号的二进制码,却没有规定这个二进制码应该如何存储。Unicode 有一些具体的实现编码,其中用途最广泛的莫属 UTF-8


UTF-8


UTF-8 是使用最广的 Unicode 的一种 Unicode 的实现方式 ,它是一种变长的编码方式,使用 1 ~ 4 个字符表示一个符号,根据不同的符号而变化字符长度,提高了 Unicode 的编码效率。先来看一下 UTF-8 对于不同字节数的符号的表示方法, x 代表可使用的二进制位:

字节数 编码规则 可表示字符数量
1 字节 0xxxxxxx 2的7次方 = 128
2 字节 11xxxxxx 10xxxxxx 2的11次方 = 2048
3 字节 1110xxxx 10xxxxxx 10xxxxxx 2的15次方 = 65536
4 字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 2的21次方 = 4194304


由上面的表很容易发现 UTF-8 的编码规则:

  • 对于单字节符号,第一位为 0,后面 7 为表示这个符号的 Unicode码。所以对于单字节符号,UTF-8 的表示方式与 ASCII 一致。
  • 对于 n 字节的符号,第一个字节的前 n 位都为 1,第 n+1 位为 0,后面的所有字节前两位均为 10,剩下的二进制位为这个字符的 Unicode码


使用这种变长编码方式,对于单字节的符号仅需使用一个字节来表示,不会造成浪费。对于汉字来说,一般都是使用三个字符来表示。对于计算机来说,也很容易区分一个字符到底占用几个字节:

  • 如果一个字节的第一位为 0,这个字节就是一个字符
  • 如果第一位为 1,连续有多少个 1,就表示当前字符占用多少个字节


除了 UTF-8,相应的还有 UTF-16。在 UTF-8 中,以 8 个二进制位表示一个字符,而在 UTF-16 中,以 16 个二进制位表示一个字符。16 个二进制位可以直接表示 65536 个字符,所以在 UTF-16 中,汉字和英文字母具有同样的地位,都是使用 16 个二进制位,即 2 个字节表示 1 个字符。对英文来说会造成浪费,但是对中文来说,可以节省存储空间。


关于字符编码,应该有了一个大概的认识,在日常使用中,我们要尽量做到编码的统一,避免出现乱码的情况。

参考文章:



相关文章
|
2月前
|
存储 监控 Java
分布式调用三大基石:超时、重试、幂等的架构级落地规范与全场景避坑指南
本文深入解析分布式调用稳定性三大基石:超时(设生死线、分层预算、中断执行)、重试(限次数/退避/幂等前提)与幂等(唯一键、原子校验、结果复用),结合全链路透传、AOP实现及高频避坑指南,提供可落地的架构级协同方案。
241 6
|
存储 NoSQL Redis
Helm安装集群整理
Helm安装集群整理
451 1
|
机器学习/深度学习 资源调度 计算机视觉
YOLOv11改进策略【注意力机制篇】| NAM注意力 即插即用模块,重新优化通道和空间注意力
YOLOv11改进策略【注意力机制篇】| NAM注意力 即插即用模块,重新优化通道和空间注意力
479 2
YOLOv11改进策略【注意力机制篇】| NAM注意力 即插即用模块,重新优化通道和空间注意力
|
存储 SQL 人工智能
Apache Flink 2.0:Streaming into the Future
本文整理自阿里云智能高级技术专家宋辛童、资深技术专家梅源和高级技术专家李麟在 Flink Forward Asia 2024 主会场的分享。三位专家详细介绍了 Flink 2.0 的四大技术方向:Streaming、Stream-Batch Unification、Streaming Lakehouse 和 AI。主要内容包括 Flink 2.0 的存算分离云原生化、流批一体的 Materialized Table、Flink 与 Paimon 的深度集成,以及 Flink 在 AI 领域的应用。
1736 13
Apache Flink 2.0:Streaming into the Future
|
传感器 自动驾驶 算法
智能无人机:物流配送与环境监测
【10月更文挑战第25天】智能无人机技术正深刻改变物流配送与环境监测领域。通过先进的自动驾驶、飞行控制及精确定位技术,智能无人机在物流配送中实现快速、准确的货物送达,显著提高配送效率。在环境监测中,无人机凭借高空监测能力和实时数据传输技术,为大气、水质等环境要素提供全面、高效的监测服务。未来,随着技术升级和应用场景拓展,智能无人机将在更多领域发挥重要作用。
|
存储 Java 程序员
Java中的位运算符详解
Java中的位运算符详解
348 1
|
数据采集 数据可视化 Java
分享66个Python爬虫源码总有一个是你想要的
分享66个Python爬虫源码总有一个是你想要的
1243 1
|
Unix Shell Linux
shell命令之more/less
shell命令之more/less
553 1
|
数据采集 Java Python
python并发编程:Python在FastAPI服务中使用多进程池加速程序运行
python并发编程:Python在FastAPI服务中使用多进程池加速程序运行
2633 0