关于字符编码你应该知道的事情有哪些_字符编码的关系

关于字符编码你应该知道的事情有哪些_字符编码的关系在计算机内部,所有的信息最终都表示为一个二进制的序列。每一个二进制位 ( Bit ) 有 0 和 1 两种状态,因此八个二进制位就可以组合出 256 种状态,这被称为一个字节 ( Byte ) ,也就是说,一个字节一共可以用来表示 256 种不同的状态或者符号。如果我们制作一张…

读完本文你将了解的知识点

  1. 为什么 Windows 上使用 Notepad 会出现乱码
  2. 为什么 Emoji 表情在有些手机上显示不准确
  3. 为什么 Emoji 在没有做过特殊优化的数据库中存储失败
  4. 为什么使用 Linux 开发的代码他人使用 Windows 开发后换行符全变了
  5. 为什么在 JS 中 [...'👨‍👨‍👦‍👦'] => ["👨", "‍", "👨", "‍", "👦", "‍", "👦"]
  6. 新版本 ECMAScript 针对 JavaScript 编码问题做了哪些改进
  7. 为什么使用 Google Chrome 打开 JS 文件,文件中的中文字符会变成乱码

比特、字节

  1. 比特 ( Bit / Binary digit ) 缩写为 b,计算机最小的存储单位,以 0/1 来表示值

  2. 字节 ( Byte ) 缩写为 B,8 个比特表示一个字节

    在计算机内部,所有的信息最终都表示为一个二进制的序列。每一个二进制位 ( Bit ) 有 0 和 1 两种状态,因此八个二进制位就可以组合出 256 种状态,这被称为一个字节 ( Byte ) ,也就是说,一个字节一共可以用来表示 256 种不同的状态或者符号。如果我们制作一张对应表格,对于每一个 8 位二进制序列,都对应唯一的一个符号。每一个状态对应一个符号,就是 256 个符号,从 0000 0000 到 1111 1111 。

ASCII 与 EASCII

  1. ASCII (American Standard Code for Information Interchange,美国信息交换标准代码)

    1967 年发布,最后更新于 1986 年,共定义了 128 ( 2⁷ ) 个字符( 0x00 – 0x7F ) ,其中 33 个字符为不可打印字符 ( 0x00 – 0x1F & 0x7F ),95 个可打印字符 ( 0x20 – 0x7E )

    可打印字符为标准键盘中可输入的字符,如下所示:

    10 个数字 ( 0-9 ),26×2 个大小写字母 ( a-z A-Z ) ,32 个标点符号 1 个空格 ( ,./;'[]\-=~!@#$%^&*()_+{}|:"<>? )

    ASCII 的局限在于只能显示 26 个基本拉丁字母、阿拉伯数目字和英式标点符号,因此只能用于显示现代美国英语,而其他携带类似于重音符号的字母无法显示 ( naïve、café )

  2. EASCII ( Extended ASCII,延伸美国标准信息交换码 )

    由于 ASCII 的天然不足,它的变种体迅速出现,兼容字符集对ASCII的处理

  • ISO/IEC 646 1972年

    该标准来自数个国家标准,最主要的是美国的 ASCII 标准,ISO 646 为了表示欧洲各种语言的带附加符号( diacritical mark )的变音字母,由于没有码位空间去直接编码这些变音字母,所以用几个标点符号来兼作变音字母的附加符号

  • ISO/IEC 8859

    扩展字符:0xA0 ( 160 ) – 0xFF ( 255 ) 淘汰了 ISO 646 编码标准

    ISO 8859 统一了此前各国各语言的单独编码的混乱局面;废弃了 ISO 646 使用的退格键开始的转义序列来表示变音字母的方法,而是在 G1 区域直接编码表示变音字母。

    ISO 8859 有 15 个子版本( 1-11,13-16 ),其中囊括了大部分欧州语言,英语因为没有重音字母,所有可以使用其中任何一个子版本表示

    Microsoft Codepage 1252 为 ISO 8859-1 的超集,扩充了 0x80 – 0x9F 来编码一些可打印字符 ( € ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ Ž ‘ ’ “ ” • – — ˜ ™ š › œ ž Ÿ )

    例如在中国 GB/T 1988-80 标准中: $ u+0024 替换为 ¥ u+00A5 ,~ u+007E 替换为 u+203E

  1. ANSI

    Windows 操作系统上的 ANSI 编码并不是指的是美国国家标准学会 ( ANSI ),而是用来指称多个不同的代码页,比如在简体中文编码操作系统中,ANSI 实际使用 GB 系字符编码

中文

  • GB2312 ( 1981 ) 6763 个汉字,最初版本,双字节编码
  • GB12345 ( 1993 ) 6866 个汉字,为了适应繁体汉字信息处理而制定的标准
  • GBK ( 1995 ) 21886个汉字和图形符号,不属于国家标准
  • GB18030 ( 2000 ),70244 个字符,基于 GBK,现行版本

国际通用标准

  • Unicode ( 万国码、国际码、统一码、单一码 )

    最初版本:1.0.0 发布,1991 年 10 月发布,7161 个字符 当前正式版本 Unicode 11.0 ( 2018 年 6 月 ) 拥有 137374 个字符 当前最新版本:Emoji 12.0 Beta

    表示方法:

    • 基本平面:通常会用 “U+” 然后紧接着 4 个 16 进制的数字来表示这一个字,可表示 6 万余个字符
    • 其他平面使用 “U-” 然后接着 8 个 16 进制数字表示
  • ISO/IEC 10646 ( UCS / 通用字符集 )

    该字符集包括了其他所有字符集,保证了与其他字符集的双向兼容,ISO 10646 有三种实现级别,不同的实现级别能支持的字符数量不同

    与 Unicode 的关系:

  • 所有字符在相同位置且有相同名字
  • Unicode 标准里有详细说明某些语言和文字的表达算法等
  • ISO 承诺,ISO 10646 将不会替超出 U+10FFFF( Unicode 编码以 U+ 开头) 的 UCS-4 编码赋值

UTF ( Unicode Transformation Format )

Unicode 是一个字符集,其实现方式称为 Unicode 转换格式,即 UTF

  • UTF-32

    Unicode 与 UCS 合并之前已经产生了 UCS-4 编码方式,UCS-4 使用了 32 位来表示每个编码,为了兼容 Unicode 产生了 UTF-32 标准,编码空间限制在了 0x000000 – 0x10FFFF 之间,因此可以说 UTF-32 是 UCS-4 的子集。由于 UTF-32 的编码空间占用过大,因此在 HTML5 标准中明确规定不能使用 UTF-32 进行编码

  • UTF-16

    UTF-16 编码拥有定长和变长两个编码特点,对于 Unicode 基本平面的字符,UTF-16 占用两个字节,对于辅助平面的字符,UTF-16 编码占用四个字节

    Unicode 规范定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做 “零宽度非换行空格 ( zero width no-break space )”,用 FE FF 表示。但在不同计算机系统中对字节顺序的理解是不一致的,即出现了大端序 ( UTF-16 BE ) 与小端序 ( UTF-16 LE ) 两种情况。文本头部使用 FE FF 与 FF FE 进行区分,此区分符称为“字节顺序标记 ( BOM ) ”

    如何确定双字节和四字节:

    在基本平面内,从 U+D800 到 U+DFFF 是一个空段,不对应任何码点,这个空段用来映射辅助平面的字符,即一个辅助平面的字符,被拆成两个基本平面的字符表示。

    例如: 👨 可以表示为 U+D83D U+DC68

  • UTF-8

    由于前两种编码方式的编码规则对与英语国家来说非常浪费(2-4 字节编码)

    UTF-8 当前使用 1-6 个字节为每个字符编码

  1. 对于单字节的符号,字节的第一位设为 0 ,后面 7 位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。

  2. 对于n字节的符号( n > 1 ),第一个字节的前n位都设为 1,第 n + 1 位设为0,后面字节的前两位一律设为 10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

  3. 带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要两个字节编码 ( Unicode 范围由 U+0080 至 U+07FF )。

  4. 其他基本多文种平面 ( BMP ) 中的字符(这包含了大部分常用字,如大部分的汉字)使用三个字节编码 ( Unicode范围由U+0800至U+FFFF )。

  5. 其他极少使用的 Unicode 辅助平面的字符使用 4-6 字节编码

  • UCS-2

    JavaScript 采用了 Unicode 字符集。但是只支持一种编码方式。JS 最先采用的编码既不是 UTF-16 也不是 UTF-32 或 UTF-8 ,而是 UCS-2 。UTF-16 明确宣布是 UCS-2 的超集。UTF-16 中基本平面字符延用 UCS-2 编码。辅助平面字符定义了 4 个字节的表示方法。

    JS 只能处理 UCS-2 编码,造成所有字符在这门语言中都是两个字节,如果是四个字节的字符。会被当做两个双字节的字符处理。

    两者的关系简单说,就是 UTF-16 取代了 UCS-2,或者说 UCS-2 整合进了 UTF-16。所以,现在只有 UTF-16,没有 UCS-2。

码点和平面

字符会从 0 开始为每个字符指定一个编码, 这个编码叫做码点

举例 Unicode 中给字符进行分区定义,每个区称为一个面,Unicode 拥有 0-16 共 17 个平面,每个平面 16⁴ 个字符

平面 字符值 描述
0号平面 U+0000 – U+FFFF 基本多文种平面
1号平面 U+10000 – U+1FFFF 多文种补充平面
2号平面 U+20000 – U+2FFFF 表意文字补充平面
3号平面 U+30000 – U+3FFFF 表意文字第三平面(未正式使用)
4 – 13号平面 U+40000 – U+DFFFF (尚未使用)
14号平面 U+E0000 – U+EFFFF 特别用途补充平面
15号平面 U+F0000 – U+FFFFF 保留作为私人使用区(A区)
16号平面 U+100000 – U+10FFFF 保留作为私人使用区(B区)

题首问题

  • 为什么 Windows 上使用 Notepad 会出现乱码

    Windows 上的 Notepad 软件在保存文件时默认使用的是 ANSI 编码保存,而在打开的时候需要猜测 txt 文件的编码方式,如果文档中出现了 ANSI 编码以外的字符,则在打开时候可能会出现编码识别错误的情况,由于 txt 文件为纯文本文件,没有保存文档编码信息的区域,则此问题可能一直存在。

    解决该问题可在保存文件的时候使用 UTF-8 编码保存,但需要注意的是:

    Windows 的 Notepad 应用使用 UTF-8 保存的时候实际使用的为 UTF-8 BOM 方式,其表现为在文本最开头添加 EF BB BF ,这部分称为 UTF-8 字节顺序标记 ,该方式并非强制标准,如果在代码文件中使用该方式保存则有可能出现运行错误。

  • 为什么 Emoji 表情在有些手机上显示不准确

    当前 iOS 12 使用的 Unicode 版本为 11,而大众使用比较的 Android 8.0 使用的Unicode 版本为 9,如果在 Android 系统中出现了新版本的字符,则会出现无法显示或显示错误的情况。

    例如在 Unicode 8.0 中加入了 5 个菲茨帕特里克修饰符,用来调节人形表情的肤色,如果在低于此版本的 Unicode 中显示的字符为两个字符,分别是颜色加人偶。

    另外 Unicode 新版本中使用 U+200D 零宽连字 ( ZWJ ) 将多个 Emoji 连起来,例如 👨‍👨‍👦‍👦 => 👨👨👦👦

  • 为什么 Emoji 在没有做过特殊优化的数据库中存储失败

    Emoji 表情占用 4 个字节,但是 MySQL 数据库使用的 utf-8 默认编码最多只能存储 3 个字节 ( UTF-8 标准支持最长编码为 6 字节 ),就会导致存储不进去,在读取的时候读取不完整,导致乱码

    修复方法为:修改数据库字符集为 uft8mb4,如果数据库连接池中对字符集作出了设置需要在链接中去掉 characterEncoding 参数

  • 为什么使用 Linux 开发的代码他人使用 Windows 开发后换行符全变了

    Windows 系列系统使用的换行标志为 CRLF,该换行标志与 Unix/Linux 的 LF 换行及 macOS 的 CR 换行不相同。 如果在代码工程中使用了 Code Lint 工具自动格式化,可能会使代码中的 LF 换行自动转换为 CRLF 换行,Git 中也能捕获或忽略这个变化。 另外,从 Windows 10 1803 开始,支持 Unix/Linux 的 LF 换行及 macOS 的 CR 换行。

  • 为什么在 JS 中 [...'👨‍👨‍👦‍👦'] => ["👨", "‍", "👨", "‍", "👦", "‍", "👦"]

    👨‍👨‍👦‍👦 是 2015 年添加到 Emoji 2.0 中的新字符,使用 U+200D 零宽连字 (ZWJ) 将4个 Emoji 连起来,可使用以下代码检测

    […’👨‍👨‍👦‍👦’].forEach(e=>{console.log(e.codePointAt().toString(16))})

  • 新版本 ECMAScript 针对 JavaScript 编码问题做了哪些改进

    由于 JavaScript 使用的是只支持双字节编码的 USC-2 编码方式,所以所有超过二字节编码的 Unicode 字符都无法在 JavaScript 中处理

    例如 '👨'.charCodeAt().toString(16) 输出的结果为 d83d ,而👨的Unicode 码点却不是 d83d,造成这样的原因为 JavaScript 只处理了该字符的前两个字节

    为了解决这些问题,ECMAScript 6 种增强了对新版本 Unicode 的支持。 例如:

    1. for of 循环中对双字节以上字符能识别正确长度
    2. Array.from 等方法能正确划分字符串
    3. 支持直接使用码点表示字符,例如'\ud83d\udc68' === '👨' === '\u{1F468}'
    4. String.fromCodePoint()String.prototype.codePointAt() 等方法代替 String.fromCharCode()String.prototype.charCodeAt() 等方法,以用于支持 UTF-16 编码字符
    5. 正则表达式提供了 u 修饰符,对正则表达式添加4字节码点的支持
    6. 提供了normalize方法,允许”Unicode正规化” ,例如:'\u01D1'.normalize() === '\u004F\u030C'.normalize()
  • 为什么使用 Google Chrome 打开 JS 文件,文件中的中文字符会变成乱码

    由于 2017 年更新的某版本 Chrome 中,去除了对 JS 文件默认编码 UTF-8 的支持,使用了系统默认编码(例如中文操作系统使用 GB18030 )对 JS 文件的解码,所以导致 JS 文件中的中文字符变成乱码。

    解决方法有两种:

    1. 在文件服务器中对返回头的 Content-Type 设置加上 charset=UTF-8
    2. 浏览器中使用插件改变网页编码方式,例如使用 FEHelper 工具

参考资料:

本文首发地址

blog.shoyuf.top

第二次在掘金上发文章,欢迎各位评论区中吐槽指正

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/12912.html

(0)

相关推荐

  • Python中strf time函数的格式指令

    Python中strf time函数的格式指令strftime()函数是Python中时间模块中的一个函数,可以将时间转换为字符串,而strptime(string,pattern)函数则是将字符串转换为时间类型。在Python中,strftime()函数常用于日期和时间的格式化,可以将日期和时间根据指定的格式指令转换为字符串。这篇文章将从多个方面涵盖strftime函数的格式指令,让读者更好地了解该函数的使用和功能。

    2024-02-11
    91
  • Python获取当前路径

    Python获取当前路径作为一名Python工程师,获取当前路径是日常工作中常常用到的操作。在Python中,获取当前路径有多种方法,本文将从多个方面对Python获取当前路径进行详细的阐述。

    2024-05-07
    73
  • Python代码实现获取当前时间

    Python代码实现获取当前时间获取当前时间是编程语言中常见的操作,Python也提供了丰富的方法来获取当前时间。在本文中,我们将介绍如何在Python中使用内置库和第三方库来获取当前时间,并对这些方法进行比较和分析。

    2024-08-04
    29
  • SQL语句实战学习 – 小小程序员「建议收藏」

    SQL语句实战学习 – 小小程序员「建议收藏」参考:https://zhuanlan.zhihu.com/p/38354000再次感谢作者的整理!! 1.数据已提前准备好了,已知有如下4张表:学生表:student 成绩表:score(学号,课程

    2023-05-27
    124
  • python制作模块与包(python 模块包)

    python制作模块与包(python 模块包)Python模块的安装方法:

    2023-11-20
    136
  • Python是什么意思?

    Python是什么意思?Python是一种高级、解释型、功能强大的编程语言。它的诞生可以追溯到20世纪80年代末期荷兰计算机科学家Guido van Rossum创造了一种新的编程语言。他在设计Python时,主要考虑了其易读性和简洁性,因此,Python使用冒号和缩进来标记代码块,这使得Python语言具有良好的可读性和可维护性。

    2024-09-05
    22
  • mysql-5.7.21

    mysql-5.7.211 、 下载对用的版本信息 地址是:https://dev.mysql.com/downloads/mysql/ 2 、 解压到目录 D: oolsmysqlmysql-5.7.21-winx6

    2022-12-28
    166
  • Python中的迭代器

    Python中的迭代器迭代器是Python编程语言中最受欢迎的特性之一,它可以让我们在处理数据集合时以一种非常优雅和简单的方式遍历数据。在本文中,我们将深入探讨Python中迭代器的工作原理、如何创建和使用迭代器,以及一些常用的迭代器工具。

    2024-04-29
    103

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注