您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

一文简简单单彻彻底底弄清文本编码

时间:2022-07-12 15:58:31  来源:今日头条  作者:百剑阁

计算机只能识别 0 和 1,任何数据格式,包括数字、文本、图像、音乐、视频等等都表示为一串由 0 和1 组成的二进制数据串。如何将一串二进制数据识别为有意义的数据类型,是软件层面的问题,是一种格式和约定。

ASCII编码

现代计算机的软硬件设计最早都是由一群以英语为母语的人设计的,英语只有52个字母(大小写区别对待),再加上常用的一些标点符号和控制符号(比如换行、回车等),也就一百来个左右。1个字节8个比特位,能表示256种状态,因此纯英文环境下的各种字符用1个字节就足够了。于是自然而然的,就诞生了ASCII 这个最早也是使用最广泛的单字节编码。

ASCII 编码使用1个字节的低7位,最高位为0,编码范围是00000000-01111111,用十进制表示的话就是0-127,其编码分布如下图所示。

 

Latin1 编码

ASCII 码表只包含了英文字母,显然是不够的。首先就是西欧国家,主要是拉丁语言。和英文一样,也是字母语言,字符不算多,大概几十个。于是ASCII最高的1位尚未使用的比特位就被利用起来了,编码范围是 10000000-11111111,即十进制的128-256,包含了拉丁字母和一些特殊符号,如欧元符号等,这就是 Latin1 编码。可以看出,Latin1 编码是 ASCII 的超集,一共能够表示 256个字符。

GB2312、GBK和GB18030编码

到了亚洲国家,情况就很复杂了。以中文为例,仅仅是最常使用,满足日常阅读书写的最少汉字,也要三千个左右,显然用单字节是无法容纳了。很自然地,人们就想,单字节不够用,那就双字节呗。

首先形成标准的是 GB2312。GB2312 采用的是变长码,即 ASCII 字符仍然用单字节表示,中文则用 2 个字节表示。具体的技术规定是:码值小于127的字符的意义和ASCII码相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1 到 0xF7,后面一个字节(低字节)从 0xA1到 0xFE。

但汉字的数量实际上是远大于这个数目的,再加上还有繁体字,GB2312 很快就无法满足需要了。于是 GBK 出现了,具体的技术方案从两个方面着手,一是把之前 GB2312 还没用完的码点继续用完,二是放宽了两个字符的码值都大于127才是中文的限制,只要第一个字符大于127就表示中文。GBK 是 GB2312 的超集,完全兼容 GB2312,收录了2万多个汉字及相关字符,包括繁体字。

到了 GBK,基本上沟通交流就不存在太大问题了,但仍然无法满足文化传播的需要,一些生僻字以及我国少数名族的字仍然无法表达。于是又引入了 GB18030 (全称《信息技术 中文编码字符集)。在 GBK 的基础上进一步扩大了覆盖范围,共收录七万多个汉字、少数民族字以及日语和韩语中的汉字。因为超过了65535 的两字节极限,GB18030 采用了变长编码,即一个字符有可能是1个字节(ASCII字符),2个字节(完全兼容GB2312,基本兼容GBK)和4个字节。

Unicode

为了适应本国需要,很多国家和地区都制定了自己的文字编码,要识别不同编码下的文字,就要安装相应的解码程序,很是不方便。浏览网页时常常出现的乱码基本上都是编码问题导致的。

为了解决这一问题,开发者就提出用一种编码统一对全世界的各种文字进行编码,给每一个字符一个唯一的码点(Code point),这就是 Unicode 。目前 Unicode 的编码空间共包含 0x10FFFF(1114111)个编码点,被划分为17个平面,每个平面包含0xFFFF 即 65535 个字符。其中最重要的是基本多文种平面(Basic Multilingual Plane),包含了各语种最常用的字符编码,码点范围为 0x0000-0xFFFF,其它平面称之为辅助平面。

从1991年发布的第一个版本开始,每一年都会有新的字符被编入Unicode中,最新的 Unicode 标准是14.0.0,共收录了 144,697 个字符。需要注意的是,Unicode 是一个符号集,一种规范,为每一个字符规定了唯一对应的数字,即码点。但并不是编码标准,因为不涉及如何存储这些码点,即前面我们所说的用几个字节存储一个字符,采用的具体技术方案等等。具体的编码标准目前主要有UTF-8、UTF-16和UTF-32。

 

UTF-32

UTF-32 是一种定长编码,用4个字节来统一表示 Unicode 字符。这个方案简单明了,码点值是多少,内存中就存多少。好处是每个字符的做占用的空间都是相同的,因此随机获取任意位置的字符就非常简单,直接在首字符的地址加上一个固定的偏移量就可以了,时间复杂度是O(1)。

UTF-32 的缺点也是显而易见的,那就是空间浪费。本来英文字母用1个字节就可以表示,现在同样需要4个字节。

UTF-16

UTF-16 是变长编码,用2个字节或者4个字节存储 Unicode 码点。

前面说过,Unicode 码点的范围是 0x000000~0x10FFFF。对于 0x0000~0xFFFF 即基本多语种平面的字符,UTF-16 用2个字节来表示,直接存储码点值。

超出 0xFFFF 码点的值,2字节存不下,采用4字节存储。那么4个字节如何表示一个 Unicode 码点呢?首先,不能直接存储码点值,因为如果直接存储码点值,前2个字节的值就有可能和基本多语言平面内的码点值相同而导致无法区分。其次,4个字节理论上能够存储42.9亿多个字符,但Unicode 规范只定义了 1114111 个字符,因为 2 的20次方大致是1,048,576,因此差不多只需要20位,即2个半字节就可以了。

具体采取的办法就是将超出 0xFFFF 的码点值分为前后两个部分,每个部分各10位。其中前面10位是基本多语种平面尚未分配的码点范围:即 0xD800~0xDBFF,共可以表示1024个状态。后面10位则规定为 0xDC00~0xDFFF,也可以表示1024个状态,合起来一共可以表示1024 * 1024 = 1,048,576 个字符,再加上基本多语言平面的字符,差不多等价于Unicode 码点范围,稍微少一点,影响不大。

UTF-8

UTF-8 也是一种变长码。编码规则是:如果首字节的高位为0,即码点在 0 - 127 之间,就是单字节编码(ASCII码)。如果第1个字节的高位为1,就是多字节编码,至于是2个字节、3个字节疑惑是4个字节,取决于第一个字节高位有连续几个1。若属于多字节编码,那么 UTF-8 除首字节外,其余字节均以10 开头。也就是说,UTF-8 理论上可以到8字节,但由于 Unicode 目前只有一百多万个码点,因此最多使用4个字节就足够了。

  • 单字节编码,形式是 0xxxxxxx,完全兼容ASCII 编码,包含127个字符。
  • 双字节编码:形式是 110xxxxx 10xxxxxx,能够容纳 2048 个字符,
  • 三字节编码:1110xxxx 10xxxxxx 10xxxxxx,能够容纳65536个字符。
  • 四字节编码:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:能够容纳 2,097,152 个字符,超出了 Unicode 码点范围

UTF-8 最大的好处是灵活,如果文本完全是英文,那么只需要单字节就可以了。汉字绝大部分是三字节编码,少部分是四字节。

大端序和小端序

计算机以字节为最小存储单位,也就是说一个字节之内是不会拆分的。但如果有两个或以上的字节(或单元),存放时谁放在前面就有区别了.比如"马"字的Unicode码值是 0x9A6C ,采用2个字节存储时,就有两种不同的考量,即第一个字节 9A 放在存储器的前面(低地址处),还是放在后面(存储器的高地址处)呢?大端序就是前面的字节放在低地址处,后面的放在高地址处;否则就是小端序。

字节序 BOM 即 Byte Order Mark。BOM 是Unicode标准中的一个特殊字符 FEFF. 它没有定义为任何字符,但在Unicode标准中推荐放在文件或数据流的开头, 用来标识字节存贮的顺序. 我们都知道它的码值是 FEFF. 如果存储为FE FF,则表明这种方式是大端序(BE), 如果存储为FF FE,则表明为小尾(LE)。

C# 中处理文本编码

在 C# 中,System.Text.Encoding 为文本编码提供了基础支持,可以通过 GetEncoding 方法获取任意编码实例。

 // 在 .NET Core中,必须休闲调用 RegisterProvider: 
 Encoding.RegisterProvider (CodePagesEncodingProvider.Instance);
 // 获取当前系统支持的所有编码
 foreach (EncodingInfo info in Encoding.GetEncodings()) 
 {
     Console.WriteLine (info.Name)
 }
 // 获取 GB18030 编码    
 var chineseEncoding = Encoding.GetEncoding ("GB18030");
 var utf8Encoding = Encoding.UTF8;

对于 ASCII、Latin1、 UTF-8 、UTF-16 和 UTF-32 等编码,C# 还提供了专门的子类。

  • Encoding.ASCII
  • Encoding.Latin1
  • Encoding.UTF8
  • Encoding.Unicode ,UTF-16编码,小端序
  • Encoding.BigEndianUnicod,UTF-16编码,大端序
  • Encoding.UTF32,UTF-32编码,小端序

在读取文件时,可以指定编码,如果不指定,一般默认为 UTF-8。

 System.IO.File.WriteAllText ("data.txt", "床前明月光", Encoding.Unicode);


Tags:文本编码   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
一文简简单单彻彻底底弄清文本编码
计算机只能识别 0 和 1,任何数据格式,包括数字、文本、图像、音乐、视频等等都表示为一串由 0 和1 组成的二进制数据串。如何将一串二进制数据识别为有意义的数据类型,是软件层...【详细内容】
2022-07-12  Search: 文本编码  点击:(259)  评论:(0)  加入收藏
▌简易百科推荐
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(2)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(7)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(13)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(9)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(11)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(9)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条