字符串及不同语言是如何抽象字符串的
前言
在日常开发中,我们经常需要接触字符串,字符串涉及了许多细微的要点知识,会在意想不到的时候攻击我们,值得总结提醒。同时,关于字符串的不同特性以及功能,不同语言做出了不同的抽象,我们也可以通过它们组合方式,一窥这些语言的设计理念。
编码
编码是 字符集中的字符 到 二进制 的映射。
- 编码 (Encode): 字符 → 二进制
- 解码 (Decode): 二进制 → 字符
因此,如果解码没有选择对应的方式,那么就得不到我们被编码的字符。
演进历史
编码随着时间,技术的发展和业务本身的需求不断演进。
这里还有两个概念,标准与实现。如:Unicode 是标准,而 UTF-8 是它的一个实现(其他实现还有 UTF-16)。而 ASCII 既是标准又是实现。
ASCII
ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是一套基于拉丁字母的字符编码,共收录了 128 个字符,用一个字节就可以存储,它等同于国际标准 ISO/IEC 646。
当我们操作单字节的 char,甚至做 char 的字面值的算术操作的时候,就是在操作 ASCII。
很明显,128 个字符是不够使用的。
ISO-8859
ASCII收录了空格及94个“可印刷字符”,足以给英语使用。但是,其他使用拉丁字母的语言(主要是欧洲国家的语言),都有一定数量的附加符号字母,故可以使用ASCII及控制字符以外的区域来储存及表示。ISO-8859 是兼容 ASCII 的。
ISO-8859 字符集是不包含中文的。而 Spring 的旧配置中,很多地方默认的 charset 就是 ISO-8859。当我们直接依赖 Spring 组件进行反序列化时,就有可能出现字符集转换的问题。
同时,中文仍然需要表示和字符集。
GBK
GBK 编码,全称为《汉字内码扩展规范》(”Guojia Biaozhun Kuozhan”,国家标准扩展),是一种在中国大陆广泛使用的字符编码方案。用两个字节来表示一个汉字,兼容 ASCII。
在今天,虽然 UTF-8 已经成为 Web 和现代应用开发的绝对主流,但在一些老的 Windows 系统、特定行业的软件或历史数据中,你仍然可能会遇到 GBK 编码。
我们日常生活中常见的乱码就是 GBK,UTF-8,ISO-8859 的冲突了,他们三者都兼容 ASCII,同时互相之间都会冲突。
Unicode
为了解决这些冲突,我们需要一个统一的标准。
Unicode,全称为Unicode标准(The Unicode Standard),其官方机构Unicode联盟所用的中文名称为统一码,又译作万国码、统一字符码、统一字符编码,是信息技术领域的业界标准,其整理、编码了世界上大部分的文字系统,使得电脑能以通用划一的字符集来处理和显示文字,不但减轻在不同编码系统间切换和转换的困扰,更提供了一种跨平台的乱码问题解决方案。
注意,虽然 unicode 被列在这里,但它是一种标准更甚一个编码,直接使用 Unicode 存储会浪费很多空间。
由它作为标准,才有了后续的许多编码方式,比如我们所广泛使用的 UTF-8。
UTF-8
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,常用大部分汉字占用3个字节,少数占用4个字节。
UTF-8 也是我们当前通用的事实标准,新的项目基本会采用 UTF-8 作为编码。
此外还有一些需要注意的,比如 Mysql 的 utf8mb4,Oracle 的 AL32UTF8,原本这两个数据库各自有最古老版本的 UTF-8 实现(Mysql 固定 3 字节,四字节字符报错;Oracle 用两个 3 字节实现 4 字节),但为了兼容新的 UTF-8 标准,包括后来越来越多的 4 字节字符,不得不各自给出新的,兼容原来标准字符集的新字符集。
在处理中文时需要额外注意
文档信息
- 本文作者:nyaaar
- 本文链接:https://nyaaarlathotep.github.io/2025/10/01/str/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)