找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 167|回复: 1

程序员必备:彻底弄懂常见的7种中文字符编码

[复制链接]
  • 打卡等级:热心大叔
  • 打卡总天数:245
  • 打卡月天数:2
  • 打卡总奖励:7719
  • 最近打卡:2025-12-05 20:56:49

350

主题

557

回帖

1万

积分

管理员

积分
10407
发表于 2024-1-2 23:56:12 | 显示全部楼层 |阅读模式
几种常见中文编码的关系如何?

几种常见中文编码之间存在兼容性,一图胜千言

[ 几种中文编码的兼容性 ]

所谓兼容性可以简单理解为子集,同时存在也不冲突

图中我们可以看出,ASCII被所有编码兼容,而最常见的UTF8与GBK之间除了ASCII部分之外没有交集,这也是平时业务中最常见的导致乱码场景,使用UTF8去读取GBK编码的文字,可能会看到各种乱码。而GB系列的几种编码,GB18030兼容GBK,GBK又兼容GB2312,下文细讲。

三、ASCII编码

ASCII编码每个字母或符号占1byte(8bits),并且8bits的最高位是0,因此ASCII能编码的字母和符号只有128个。有一些编码把8bits最高位为1的后128个值也编码上,使得1byte可以表示256个值,但是这属于扩展的ASCII,并非标准ASCII。通常所说的标准ASCII只有前128个值!
ASCII编码几乎被世界上所有编码所兼容(UTF16和UTF32是个例外),因此如果一个文本文档里面的内容全都由ASCII里面的字母或符号构成,那么不管你如何展示该文档的内容,都不可能出现乱码的情况。

[ ASCII编码表 ]
四、GB2312、GBK、GB18030编码

GB全称GuoBiao国标,GBK全称GuoBiaoKuozhan国标扩展。GB18030编码兼容GBK,GBK兼容GB2312,其实这三种编码有着非常深厚的渊源,我们放在一起进行比较。

【GB2312】
最早一版的中文编码,每个字占据2bytes。由于要和ASCII兼容,那这2bytes最高位不可以为0了(否则和ASCII会有冲突)。在GB2312中收录了6763个汉字以及682个特殊符号,已经囊括了生活中最常用的所有汉字。(GB2312编码全表:链接
GB2312编码表有个值得注意的点,这个表中也有一些数字和字母,与ASCII里面的字母非常像。例如A3B2对应的是数字2(如下图),但是ASCII里面50(十进制)对应的也是数字2。他们的区别就是输入法中所说的“半角”和“全角”。全角的数字2占两个字节。
通常,我们在打字或编程中都使用半角,即ASCII来编写数字或英文字母。特别是编程中,如果写全角的数字或字母,编译器很有可能不认识……

[ GB2312与ASCII重合的部分字符 ]

【GBK】
由于GB2312只有6763个汉字,我汉语博大精深,只有6763个字怎么够?于是GBK中在保证不和GB2312、ASCII冲突(即兼容GB2312和ASCII)的前提下,也用每个字占据2bytes的方式又编码了许多汉字。经过GBK编码后,可以表示的汉字达到了20902个,另有984个汉语标点符号、部首等。值得注意的是这20902个汉字还包含了繁体字,但是该繁体字与台湾Big5编码不兼容,因为同一个繁体字很可能在GBK和Big5中数字编码是不一样的。(GBK编码全表:链接

【GB18030】
然而,GBK的两万多字也已经无法满足我们的需求了,还有更多可能你自己从来没见过的汉字需要编码。
这时候显然只用2bytes表示一个字已经不够用了(2bytes最多只有65536种组合,然而为了和ASCII兼容,最高位不能为0就已经直接淘汰了一半的组合,只剩下3万多种组合无法满足全部汉字要求)。因此GB18030多出来的汉字使用4bytes编码。当然,为了兼容GBK,这个四字节的前两位显然不能与GBK冲突(实操中发现后两位也并没有和GBK冲突)。
我国在2000年和2005年分别颁布的两次GB18030编码,其中2005年的是在2000年基础上进一步补充。至此,GB18030编码的中文文件已经有七万多个汉字了,甚至包含了少数民族文字。有兴趣的可以到国家标准委官网了解详情,链接
GB2312,GBK,GB18030都是采取了固定长度的办法来解决字符分隔(即前文所提的第2件事情)问题。GBK和GB2312比ASCII多出来的字都是2bytes,GB18030比GBK多出来的字都是4bytes。至于他们具体是如何做到兼容的,可以参考下图:

[ 几种不同编码的前2字节值域 ]

这图中展示了前文所述的几种编码在编码完成后,前2个byte的值域(用16进制表示)。每个byte可以表示00到FF(即0至255)。ASCII编码由于是单字节,所以没有第2位。因为GBK兼容GB2312,所以理论上上图中GB2312的领土面积也可以算在GBK的范围内,GB18030也同理。
上图只是展示出了比之前编码“多”出来的面积。GB18030由于是4bytes编码,上图只是展示了前2bytes的值域,虽然面积最小,但是如果后2bytes也算上,GB18030新编码的字数实际上远远多于GBK。
可以看出为了做到兼容性,以上所有编码的前2bytes做到了相互值域不冲突,这样就可以允许几种不同编码中的文字同时出现在同一个文本文件中。只要全都按照GB18030编码的规则去解析并展示文件,就不会有乱码出现。实际业务中GB18030很少提到,通常GBK见得比较多,这是因为如果你去看一下GB18030里面所编码的文字,你会发现自己一个字也不认识……

[ GB18030编码的部分汉字 ]
五、UTF8编码(Unicode Transformation Format)

99%的前端写网页时都会加上<meta charset="utf-8">,99%的后端工程师新建数据库表时都会加上DEFAULT CHARSET=utf8(剩下的1%应该是忘了写)。
之所以我们想让UTF8一统天下,就是因为UTF8可以表示出世界上所有的文字!UTF8与前面说的GB系列编码不兼容,所以如果一个文件中即有UTF8编码的文字,又有GB18030编码的文字,那绝对会有乱码。
Unicode赋予了全世界所有文字和符号一个独一无二的数字编号,UTF8所做的事情就是把这个数字编号表示出来(即解决前文提到的第2件事情)。UTF8解决字符间分隔的方式是数二进制中最高位连续1的个数来决定这个字是几字节编码。0开头的属于单字节,和ASCII码重合,做到了兼容。

以三字节为例,开头第一个字节的”1110”,有连续三个1,说明包括本字节在内,接下来三个字节一起构成了一个文字。凡是不属于文字首字节的byte都以“10”开头,上表中标注X的位置才是真正用来表示Unicode数值的。
这种巧妙设计,把Unicode的数值和每个字的字节数融合在一起,最坏情况是6个字节表示一个字,已经足够表示世界上所有语言的所有文字了。不过从这种表示方式也可以很显然地看出来,UTF8和GBK没有任何关系,除了都兼容ASCII以外。

[ &amp;amp;amp;amp;amp;quot;鹅&amp;amp;amp;amp;amp;quot;字的UTF8编码计算过程 ]
举例说明,中文“鹅”字,Unicode十进制值为40517(16进制为9E45,2进制为1001 1110 0100 0101)。这个2进制值长度为12位,查询上面表格发现,二字节不够表示,四字节太长,三字节刚好,因此可以表示为 11101001 10111001 10000101,换算为16进制即E9B985,这就是“鹅”字的UTF8编码,占3字节。另外,经查询,“鹅”的GBK编码为B6EC,和UTF8的值完全不相干。
对于中文汉字来说,所有常用汉字的Unicode值都可以用3字节的UTF8表示出来,而GBK编码的汉字基本是2字节(GB18030虽4字节但是日常没人会写那些字)。这也就导致了,如果把GBK编码的中文文本另存为UTF8编码,体积会大50%左右。这也是UTF8的一点小瑕疵,存储同样的汉字,体积比GBK要大50%。
不过在“可表示世界上所有文字”这一巨大优势面前,UTF8的这点小瑕疵可以忽略了,所以日常开发中最常使用UTF8。

六、其他经常遇到的编码

【ANSI编码】
准确说,并不存在哪种具体的编码方式叫做ANSI,它只是一个Windows操作系统上的别称而已。在中文简体Windows操作系统上,ANSI就是GBK;在泰语操作系统上,ANSI就是TIS-620(一种泰语编码);在韩语操作系统上,ANSI就是EUC-KR(一种韩语编码)。并且所谓的ANSI只存在于Windows操作系统上。

【Latin1编码(又名ISO-8859-1编码)】
相信99%的人第一次听到Latin1都是在使用Mysql数据库的时候接触到的。Latin1是Mysql数据库表的默认编码方式。Latin1也是单字节编码方式,也就是说最多只能表示256个字母或符号,并且前128个和ASCII完全吻合。
Latin1在ASCII基础上又充分利用了后面那128个值,赋予他们一些泰语、希腊语等字母或符号,将1个字节的256个值全部占满了。因为项目中用不到,我对这种编码的细节没兴趣了解,唯一感兴趣的是为什么Mysql选它做默认编码(为什么默认编码不是UTF8)?以及如果忘了设置Mysql表的编码方式时,用Latin1存储中文会不会出问题?

[ Latin1编码表 ]

为什么默认编码是Latin1而不是UTF8?原因之一是Mysql最开始是某瑞典公司搞的项目,故默认collate都是latin1_swedish_ci。swedish可以理解为其私心,不过latin1不管是否出于私心目的,单字节编码作为默认值肯定是比多字节做默认值更不容易在插入数据时报错。
既然Latin1为单字节编码,并且将1个字节的所有256个值全部占满,因此理论上把任何编码的值塞到Latin1字段都是可以存的(无非就是显示乱码而已)。
假设默认为UTF8这一多字节编码,在用户误把一个不使用UTF8编码的字符串存进去时,很有可能因为该字符串不符合UTF8的编码要求导致Mysql根本没法处理。这也是单字节编码的一大好处:显示可以乱码,但是里面的数据值永远正确。
用Latin1存储中文有没有问题?答案是没有问题,但是并不建议。例如你把UTF8编码的“讯”字(UTF8编码为0xE8AEAF,占三个字节)存入了Latin1编码的Mysql表,那么在Mysql眼里,你存入的并不是一个“讯”字,而是三个Latin1的字母(0xE8,0xAE,0xAF)。本质上,你存的数据值依然是0xE8AEAF,这种“欺骗”Mysql的行为并没有导致数据丢失,只不过你需要注意读取出来该值的时候,自己要以UTF8编码的方式显示出来,要不然就是乱码。
因此,用Latin1存任何文字技术上都可以,但是经常会导致数据显示乱码。通常的解决方案,就是让UTF8一统天下,建表的时候就声明charset为utf8。
文章最后,遗留一个问题。既然有这么多编码形式,如果给定一个文本文件,不告诉你是什么编码,如何用程序进行检测?比较有代表性的编码检测库为python的chardet,其具体的原理,且待下回分解~

论坛免责声明
版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。
  • 打卡等级:热心大叔
  • 打卡总天数:245
  • 打卡月天数:2
  • 打卡总奖励:7719
  • 最近打卡:2025-12-05 20:56:49

350

主题

557

回帖

1万

积分

管理员

积分
10407
 楼主| 发表于 2024-1-2 23:59:37 | 显示全部楼层
计算机起源于美国,上个世纪,他们对英语字符与二进制位之间的关系做了统一规定,并制定了一套字符编码规则,这套编码规则被称为ASCII编码
ASCII 编码一共定义了128个字符的编码规则,用七位二进制表示 ( 0x00 - 0x7F ), 这些字符组成的集合就叫做 ASCII 字符集
随着计算机的普及,在不同的地区和国家又出现了很多字符编码,比如: 大陆的 GB2312、港台的 BIG5, 日本的 Shift JIS等等
由于字符编码不同,计算机在不同国家之间的交流变得很困难,经常会出现乱码的问题,比如:对于同一个二进制数据,不同的编码会解析出不同的字符
当互联网迅猛发展,地域限制打破之后,人们迫切的希望有一种统一的规则, 对所有国家和地区的字符进行编码,于是 Unicode 就出现了
Unicode 简介
Unicode 是国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换
Unicode 字符集的编码范围是 0x0000 - 0x10FFFF , 可以容纳一百多万个字符, 每个字符都有一个独一无二的编码,也即每个字符都有一个二进制数值和它对应,这里的二进制数值也叫 码点 , 比如:汉字 "中" 的 码点是 0x4E2D, 大写字母 A 的码点是 0x41, 具体字符对应的 Unicode 编码可以查询 Unicode字符编码表
字符集和字符编码
字符集是很多个字符的集合,例如 GB2312 是简体中文的字符集,它收录了六千多个常用的简体汉字及一些符号,数字,拼音等字符
字符编码是 字符集的一种实现方式,把字符集中的字符映射为特定的字节或字节序列,它是一种规则
比如:Unicode 只是字符集,UTF-8、UTF-16、UTF-32 才是真正的字符编码规则
Unicode 字符存储
Unicode 是一个符号集, 它只规定了每个符号的二进制值,但是符号具体如何存储它并没有规定
前面提到, Unicode 字符集的编码范围是 0x0000 - 0x10FFFF,因此需要 1 到 3 个字节来表示
那么,对于三个字节的 Unicode字符,计算机怎么知道它表示的是一个字符而不是三个字符呢 ?
如果所有字符都用三个字节表示,那么对于那些一个字节就能表示的字符来说,有两个字节是无意义的,对于存储来说,这是极大的浪费,假如 , 一个普通的文本, 大部分字符都只需一个字节就能表示,现在如果需要三个字节才能表示,文本的大小会大出三倍左右
因此,Unicode 出现了多种存储方式,常见的有 UTF-8、UTF-16、UTF-32,它们分别用不同的二进制格式来表示 Unicode 字符
UTF-8、UTF-16、UTF-32 中的 "UTF" 是 "Unicode Transformation Format" 的缩写,意思是"Unicode 转换格式",后面的数 字表明至少使用多少个比特位来存储字符, 比如:UTF-8 最少需要8个比特位也就是一个字节来存储,对应的, UTF-16 和 UTF-32 分别需要最少 2 个字节 和 4 个字节来存储
UTF-8 编码
UTF-8: 是一种变长字符编码,被定义为将码点编码为 1 至 4 个字节,具体取决于码点数值中有效二进制位的数量
UTF-8 的编码规则:
  • 对于单字节的符号,字节的第一位设为 0,后面 7 位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的, 所以 UTF-8 能兼容 ASCII 编码,这也是互联网普遍采用 UTF-8 的原因之一
  • 对于 n 字节的符号( n > 1),第一个字节的前 n 位都设为 1,第 n + 1 位设为 0,后面字节的前两位一律设为 10 。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码
下表是Unicode编码对应UTF-8需要的字节数量以及编码格式
Unicode编码范围(16进制)UTF-8编码方式(二进制)
表格中第一列是Unicode编码的范围,第二列是对应UTF-8编码方式,其中红色的二进制 "1""0" 是固定的前缀, 字母 x 表示可用编码的二进制位
根据上面表格,要解析 UTF-8 编码就很简单了,如果一个字节第一位是 0 ,则这个字节就是一个单独的字符,如果第一位是 1 ,则连续有多少个 1 ,就表示当前字符占用多少个字节
下面以 "中" 字 为例来说明 UTF-8 的编码,具体的步骤如下图, 为了便于说明,图中左边加了 1,2,3,4 的步骤编号



首先查询 "中" 字的 Unicode 码 0x4E2D, 转成二进制, 总共有 16 个二进制位, 具体如上图 步骤1 所示
通过前面的 Unicode 编码和 UTF-8 编码的表格知道,Unicode 码 0x4E2D 对应 000800 - 00FFFF 的范围,所以, "中" 字的 UTF-8 编码 需要 3 个字节,即格式是 1110xxxx 10xxxxxx 10xxxxxx
然后从 "中" 字的最后一个二进制位开始,按照从后向前的顺序依次填入格式中的 x 字符,多出的二进制补为 0, 具体如上图 步骤2、步骤3 所示
于是,就得到了 "中" 的 UTF-8 编码是 11100100 10111000 10101101, 转换成十六进制就是 0xE4B8AD, 具体如上图 步骤4 所示
UTF-16 编码
UTF-16 也是一种变长字符编码, 这种编码方式比较特殊, 它将字符编码成 2 字节 或者 4 字节
具体的编码规则如下:
  • 对于 Unicode 码小于 0x10000 的字符, 使用 2 个字节存储,并且是直接存储 Unicode 码,不用进行编码转换
  • 对于 Unicode 码在 0x100000x10FFFF 之间的字符,使用 4 个字节存储,这 4 个字节分成前后两部分,每个部分各两个字节,其中,前面两个字节的前 6 位二进制固定为 110110,后面两个字节的前 6 位二进制固定为 110111, 前后部分各剩余 10 位二进制表示符号的 Unicode 码 减去 0x10000 的结果
  • 大于 0x10FFFF 的 Unicode 码无法用 UTF-16 编码
下表是Unicode编码对应UTF-16编码格式
Unicode编码范围(16进制)具体Unicode码(二进制)UTF-16编码方式(二进制)字节
表格中第一列是Unicode编码的范围,第二列是 具体Unicode码的二进制 ( 第二行的第二列表示的是 Unicode 码 减去 0x10000 后的二进制 ) , 第三列是对应UTF-16编码方式,其中红色的二进制 "1""0" 是固定的前缀, 字母 xy 表示可用编码的二进制位, 第四列表示 编码占用的字节数
前面提到过,"中" 字的 Unicode 码是 4E2D, 它小于 0x10000,根据表格可知,它的 UTF-16 编码占两个字节,并且和 Unicode 码相同,所以 "中" 字的 UTF-16 编码为 4E2D
我从 Unicode字符表网站 找了一个老的南阿拉伯字母, 它的 Unicode 码是: 0x10A6F , 可以访问 https://unicode-table.com/cn/10A6F/ 查看字符的说明, Unicode 码对应的字符如下图所示



下面以这个 老的南阿拉伯字母的 Unicode 码 0x10A6F 为例来说明 UTF-16 4 字节的编码,具体步骤如下,为了便于说明,图中左边加了 1,2,3,4 、5的步骤编号



首先把 Unicode 码 0x10A6F 转成二进制, 对应上图的 步骤 1
然后把 Unicode 码 0x10A6F 减去 0x10000, 结果为 0xA6F 并把这个值转成二进制 00 00000010 10 01101111,对应上图的 步骤 2
然后 从二进制 00 00000010 10 01101111 的最后一个二进制为开始,按照从后向前的顺序依次填入格式中的 xy 字符,多出的二进制补为 0, 对应上图的 步骤 3、 步骤 4
于是,就计算出了 Unicode 码 0x10A6F 的 UTF-16 编码是 11011000 00000010 11011110 01101111 , 转换成十六进制就是 0xD802DE6F, 对应上图的 步骤 5
UTF-32 编码
UTF-32 是固定长度的编码,始终占用 4 个字节,足以容纳所有的 Unicode 字符,所以直接存储 Unicode 码即可,不需要任何编码转换。虽然浪费了空间,但提高了效率。
UTF-8、UTF-16、UTF-32 之间如何转换
前面介绍过,UTF-8、UTF-16、UTF-32 是 Unicode 码表示成不同的二进制格式的编码规则,同样,通过这三种编码的二进制表示,也能获得对应的 Unicode 码,有了字符的 Unicode 码,按照上面介绍的 UTF-8、UTF-16、UTF-32 的编码方法 就能转换成任一种编码了
UTF 字节序
最小编码单元是多字节才会有字节序的问题存在,UTF-8 最小编码单元是一字节,所以 它是没有字节序的问题,UTF-16 最小编码单元是 2 个字节,在解析一个 UTF-16 字符之前,需要知道每个编码单元的字节序
比如:前面提到过,"中" 字的 Unicode 码是 4E2D, "ⵎ" 字符的 Unicode 码是 2D4E, 当我们收到一个 UTF-16 字节流 4E2D 时,计算机如何识别它表示的是字符 "中" 还是 字符 "ⵎ" 呢 ?
所以,对于多字节的编码单元,需要有一个标记显式的告诉计算机,按照什么样的顺序解析字符,也就是字节序,字节序分为 大端字节序 和 小端字节序
小端字节序简写为 LE( Little-Endian ), 表示 低位字节在前,高位字节在后, 高位字节保存在内存的高地址端,而低位字节保存在内存的低地址端
大端字节序简写为 BE( Big-Endian ), 表示 高位字节在前,低位字节在后,高位字节保存在内存的低地址端,低位字节保存在在内存的高地址端
下面以 0x4E2D 为例来说明大端和小端,具体参见下图:



数据是从高位字节到低位字节显示的,这也更符合人们阅读数据的习惯,而内存地址是从低地址向高地址增加
所以,字符0x4E2D 数据的高位字节是 4E,低位字节是 2D
按照大端字节序的高位字节保存内存低地址端的规则,4E 保存到低内存地址 0x10001 上,2D 则保存到高内存地址 0x10002
对于小端字节序,则正好相反,数据的高位字节保存到内存的高地址端,低位字节保存到内存低地址端的,所以 4E 保存到高内存地址 0x10002 上,2D 则保存到低内存地址 0x10001
BOM
BOM 是 byte-order mark 的缩写,是 "字节序标记" 的意思, 它常被用来当做标识文件是以 UTF-8、UTF-16 或 UTF-32 编码的标记
在 Unicode 编码中有一个叫做 "零宽度非换行空格" 的字符 ( ZERO WIDTH NO-BREAK SPACE ), 用字符 FEFF 来表示
对于 UTF-16 ,如果接收到以 FEFF 开头的字节流, 就表明是大端字节序,如果接收到 FFFE, 就表明字节流 是小端字节序
UTF-8 没有字节序问题,上述字符只是用来标识它是 UTF-8 文件,而不是用来说明字节顺序的。"零宽度非换行空格" 字符 的 UTF-8 编码是 EF BB BF, 所以如果接收到以 EF BB BF 开头的字节流,就知道这是UTF-8 文件

下面的表格列出了不同 UTF 格式的固定文件头
UTF编码固定文件头

根据上面的 固定文件头,下面列出了 "中" 字在文件中的存储 ( 包含文件头 )
编码固定文件头
常见的字符编码的问题
  • Redis 中文key的显示
有时候我们需要向redis中写入含有中文的数据,然后在查看数据,但是会看到一些其他的字符,而不是我们写入的中文



上图中,我们向redis 写入了一个 "中" 字,通过 get 命令查看的时候无法显示我们写入的 "中" 字
这时候加一个 --raw 参数,重新启动 redis-cli 即可,也即 执行 redis-cli --raw 命令启动redis客户端,具体的如下图所示



  • MySQL 中的 utf8 和 utf8mb4
MySQL 中的 "utf8" 实际上不是真正的 UTF-8, "utf8" 只支持每个字符最多 3 个字节, 对于超过 3 个字节的字符就会出错, 而真正的 UTF-8 至少要支持 4 个字节
MySQL 中的 "utf8mb4" 才是真正的 UTF-8

下面以 test 表为例来说明, 表结构如下:
  1. mysql> show create table test\G
  2. *************************** 1. row ***************************
  3.        Table: test
  4. Create Table: CREATE TABLE `test` (
  5.   `name` char(32) NOT NULL
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  7. 1 row in set (0.00 sec)
复制代码




向 test 表分别插入 "中" 字 和 Unicode 码为 0x10A6F 的字符,这个字符需要从 https://unicode-table.com/cn/10A6F/ 直接复制到 MySQL 控制台上,手工输入会无效,具体的执行结果如下图:



从上图可以看出,插入 "中" 字 成功,插入 0x10A6F 字符失败,错误提示无效的字符串,\xF0\X90\XA9\xAF 正是 0x10A6F 字符的 UTF-8 编码,占用 4 个字节, 因为 MySQL 的 utf8 编码最多只支持 3 个字节,所以插入会失败

把 test 表的字符集改成 utf8mb4 , 排序规则 改成 utf8bm4_unicode_ci, 具体如下图所示:




字符集和排序方式修改之后,再次插入 0x10A6F 字符, 结果是成功的,具体执行结果如下图所示



上图中,set names utf8mb4 是为了测试方便,临时修改当前会话的字符集,以便保持和 服务器一致,实际解决这个问题需要修改 my.cnf 配置中 服务器和客户端的字符集
小结
本文从字符编码的历史介绍了 Unicode 出现的原因,接着介绍了 Unicode 字符集中 三种不同的编码方式: UTF-8、UTF-16、UTF-32 以及它们的的编码方法,紧接着介绍了 字节序、BOM ,最后讲到了字符集在 MySQL 和 Redis 应用中常见的问题以及解决方案 ,更多关于 Unicode 的介绍请参考 Unicode 的 RFC 文档

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Discuz! X

GMT+8, 2025-12-7 11:44 , Processed in 0.026652 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表