ASCII、Unicode、UCS-2、UTF-8互转编码原理

news2024/12/22 18:53:09

基础

ASCII (American Standard Code for Information Interchange),1967年

GB2312 是中华人民共和国国家汉字信息交换用编码,国家标准总局发布,1981年5月1日实施,对应的国标标准号:GB/T 2312-1980

Unicode 1990年开始研发,1994年发布初版

其实还有比如日本 Shift-JIS,韩国EUC-KR

各式各样的编码,其实原理就是把用到的符号定义一个编号。

背景

在文件流读写的时候,对字节流和字符流的一个匹配关系产生了兴趣,比如一个文本文件存储结构是什么,为什么文件会乱码等一系列探索做个记录

正文

1. ASCII码

ASCII码,实际范围为(0x00 到 0x7F)【00000000~01111111】0~127,已被国际标准化组织ISO采纳,作为国际通用的信息交换标准代码。
在计算机内部, 所有的信息最终都表示为一个二进制的字符串. 每一个二进制位(bit)有0和1两种状态, 因此八个二进制位就可以组合出 256种状态, 这被称为一个字节(byte). 也就是说, 一个字节一共可以用来表示256种不同的状态, 每一个状态对应一个符号, 就是256个符号, 从 0000000到11111111.上个世纪60年代, 美国制定了一套字符编码, 对英语字符与二进制位之间的关系, 做了统一规定. 这被称为ASCII码, 一直沿用至今.ASCII码一共规定了128个字符的编码,  这128个符号(包括32个不能打印出来的控制符号), 只占用了一个字节的后面7位, 最前面的1位统一规定为0.

其中:

0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符)
32~126(共95个)是字符(32是空格),其中48~57为0到9十个阿拉伯数字。
65~90为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。

ASCII码表具体情况可以参考

ASCII缺点

ASCII的局限在于只能显示26个基本拉丁字母、阿拉伯数字和英式标点符号。因此,现在的软件系统大多采用Unicode,特别是与ASCII向下兼容的UTF-8
对于亚洲国家的文字, 使用的符号就更多了, 汉字就多达10万左右. 一个字节只能表示256种符号, 肯定是不够的, 就必须使用多个字节表达一个符号. 比如, 简体中文常见的编码方式是GB2312, 使用两个字节表示一个汉字, 所以理论上最多可以表示256x256=65536个符号.


2. Unicode

Unicode官网:https://home.unicode.org/ 
2.1 Unicode的定义

Unicode的范围为 【0-0x10FFFF】,换算成10进制为【0-1114111】有0-1,114,112个字符,所以100多万个字符是足以支持世界上的任何语言的

世界上存在着多种编码方式, 同一个二进制数字可以被解释成不同的符号. 因此, 要想打开一个文本文件, 就必须知道它的编码方式, 否则用错误的编码方式解读, 就会出现乱码.为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样.

可以想象, 如果有一种编码, 将世界上所有的符号都纳入其中. 每一个符号都给予一个独一无二的编码, 那么乱码问题就会消失. 这就是Unicode, 就像它的名字都表示的, 这是一种所有符号的编码.

Unicode也是一种字符编码方法, 不过它是由国际组织设计, 可以容纳全世界所有语言文字的编码方案. Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS. UCS可以看作是"Unicode Character Set"的缩写.

Unicode当然是一个很大的集合, 现在的规模可以容纳100多万个符号. 每个符号的编码都不一样, 比如, U+0639表示阿拉伯字母Ain, U+0041表示英语的大写字母A, U+4E2D表示汉字中国的"中". 具体的符号对应表, 可以查询unicode.org, 或者专门的汉字对应表.

2.2 Unicode的问题

需要注意的是, "Unicode只是一个符号集, 它只规定了符号的二进制代码, 没规定这个二进制代码应该如何存储"。

比如, 汉字"中"的unicode是十六进制数4E2D, 转换成二进制数足足有15位(100111000101101), 也就是说这个符号的表示至少需要2个字节. 表示其他更大的符号,可能需要3个字节或者4个字节, 甚至更多。

这里就有两个问题,

第一个问题是, 如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号, 而不是分别表示三个符号呢?

第二个问题是, 我们已经知道,英文字母只用一个字节表示就够了, 如果unicode统一规定, 每个符号用三个或四个字节表示, 那么每个英文字母前都必然有二到三个字节是0, 这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍, 这是无法接受的.

它们造成的结果是:

1) 出现了unicode的多种存储方式, 也就是说有许多种不同的二进制格式,可以用来表示unicode.
2) unicode在很长一段时间内无法推广, 直到互联网的出现

注意:Unicode只是一个符号集,它只规定了各个字符所对应的二进制数,并不是为了计算机系统专门设计的,没有规定在计算机中如何存储。

2.3 UCS(Unicode的定长字符编码)

【这部分参考了:https://blog.csdn.net/qq_52102933/article/details/126595077】
  通用多八位编码字符集(Universal Multiple-Octet Coded Character Set)也叫通用字符集(Universal Character Set, UCS),是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的标准字符集。

通用多八位编码字符集包括了其他所有字符集。它保证了与其他字符集的双向兼容,即,如果你将任何文本字符串翻译到UCS格式,然后再翻译回原编码,你不会丢失任何信息。

UCS-2

定长2个字节,这个不等于UTF-16
UCS-2(Universal Character Set coded in 2 octets),是用定长2个字节来表示字符(定长编码,ASCII码部分的字符存储也是2个字节),其取值范围为 U+0000~U+FFFF。Unicode当前默认的版本是UCS-2,UCS-2 编码 与 Unicode码 完全一样,6w+的字符量已经足以用于全球的主要语言的大多数字符。

可以参考以下截图:中(4e2d)国(56fd)A(0041)a(0061)

UCS-4
定长4个字节,这个等同于UTF-32,但这种我实践过程中是很少用,因为最少需要4个字节存储一个符号,比如一个字母A就需要4个字节存储(原本一个字节就够了),会特别浪费资源。

UCS-4,用四个字节表示代码点,最高位为0,取值范围为 (U+00000000~U+7FFFFFFF),允许表示一百多万个字符

比如,英文字母“A”对应的Unicode(十六进制)是U+0041,转换为十进制是65,转换为二进制是0100 0001,和ASCII码一致,只需要一个字节表示。

比如,中文“一”对应的Unicode(十六进制)是U+4E00,转换为十进制是19968,转换为二进制是100 1110 0000 0000,这个二进制有15位,需要至少2个字节表示。

具体的符号对应表,可以查询Unicode官网,也可以查询专门的汉字对应表,还有字符与Unicode编码在线转换。

3. UTF-8

UTF-8最大的一个特点, 就是它是一种变长的编码方式. 它可以使用1~4个字节表示一个符号, 根据不同的符号而变化字节长度。

互联网的普及, 强烈要求出现一种统一的编码方式. UTF-8就是在互联网上使用最广的一种unicode的实现方式. 其他实现方式还包括UTF-16和UTF-32, 不过在互联网上基本不用.重复一遍, 这里的关系是, UTF-8是Unicode的实现方式之一。

对比UTF-8UTF-16UTF-32UCS-2UCS-4
编码空间0 ~ 10FFFF0 ~ 10FFFF0 ~ 10FFFF0 ~ FFFF0 ~ 7FFFFFFF
最少编码字节数12424
最多编码字节数44424
是否依赖字节序

3.1 UTF-8的编码规则
UTF-8的编码规则很简单, 只有两条:
1) 对于单字节的符号, 字节的第一位设为0, 后面7位为这个符号的unicode码. 因此对于英语字母, UTF-8编码和ASCII码是相同的。
2) 对于n字节的符号(n>1), 第一个字节的前n位都设为1, 第n+1位设为0, 后面字节的前两位一律设为10. 剩下的没有提及的二进制位, 全部为这个符号的unicode码。

下表总结了编码规则, 字母x表示可用编码位

下面, 还是以汉字"中"为例, 演示如何实现UTF-8编码.
已知"中"的unicode是4E2D(100111000101101), 根据上表, 可以发现4E2D处在第三行的范围内(0000 0800 - 0000 FFFF), 因此"中"的UTF-8编码需要三个字节, 即格式是"1110xxxx 10xxxxxx 10xxxxxx". 然后,从"中"的最后一个二进制位开始, 依次从后向前填入格式中的x, 多出的位补0. 这样就得到了, "中"的UTF-8编码是 "11100100 10111000 10101101", 转换成十六进制就是E4B8AD.


4. Little endian和Big endian

Unicode码可以采用UCS-2格式直接存储. 以汉字"中"为例, Unicode码是4E2D, 需要用两个字节存储, 一个字节是4E, 另一个字节是2D. 存储的时候, 4E在前,2D在后, 就是Big endian方式; 2D在前, 4E在后, 就是Littleendian方式.// Big Endian(4E2D) Little Endian(2D4E)

因此, 第一个字节在前, 就是"大头方式"(Big endian), 第二个字节在前就是"小头方式"(Little endian)。

4.1 计算机如何判定是哪一种编码?(零宽度非换行空格(FEFF)),这个也就BOM
Unicode规范中定义, 每一个文件的最前面分别加入一个表示编码顺序的字符, 这个字符的名字叫做"零宽度非换行空格"(ZERO WIDTH NO-BREAK SPACE), 用FEFF表示. 这正好是两个字节, 而且FF比FE大1.// Big Endian(FEFF),Little Endian(FFFE)
如果一个文本文件的头两个字节是FE FF, 就表示该文件采用大头方式; 如果头两个字节是FF FE, 就表示该文件采用小头方式。
此处使用Notepad++进行演示

以二进制方式打开效果(插件里有一个HEX-Editor可以查看二进制):

5. Unicode与UTF-8之间的转换(javascript)

6.思考探索

我在用python获取文件的编码格式,发现没有那种一个属性就可以获取到这个编码格式,其实这个就可以理解什么是BOM 字节顺序标记(Byte Order Mark),通过通过占用几个字符来标记编码格式

import chardet
 
def get_file_encoding(file_path):
    with open(file_path, 'rb') as f:
        raw_data = f.read()
    result = chardet.detect(raw_data)
    encoding = result['encoding']
    return encoding

举例,可以看到我文件中有两个字符,实际文件大小只有2个字节,也就是这个文件中其实是没有地方去记录自己是用的是UTF-8还是GB2312的

然后我使用UTF-8 BOM格式存储,前面放置了3个字符用来标记 自己是UTF-8的格式

总结 

如非特别指定,建议还是使用UTF-8编码,毕竟浏览器的网络流已经指定默认的编码就是UTF-8,一般系统默认了UTF-8,减少因编码带来的排障

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2132480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【聊聊AI编程必不可少的NLTK及其punkt、punkt_tab安装】

聊聊AI编程必不可少的NLTK及其punkt、punkt_tab安装 前言一、NLTK是什么?二、安装NLTK1.通过cmd安装:2.通过conda安装: 三.下载NLTK Data数据包1.官网下载2.Github下载3.Gitee下载3.1 下载并安装nltk_data3.2 下载并安装punkt_tab 4. nltk_da…

开展文化创新与传承 全球老子圣像评选启动

9月11日,在刚见证了中华社会文化发展基金会老子文化公益基金成立发布会盛典的中华文化园,又迎来了中华社会文化发展基金会领导的亲临指导。本次指导由中华社会文化发展基金会执行副秘书长蒋晔带队,魏欣主任和高凯主任同行,共同考察…

RNN发展(RNN/LSTM/GRU/GNMT/transformer/RWKV)

RNN到GRU参考: https://blog.csdn.net/weixin_36378508/article/details/115101779 tRANSFORMERS参考: seq2seq到attention到transformer理解 GNMT 2016年9月 谷歌,基于神经网络的翻译系统(GNMT),并宣称GNMT在多个主…

3D培训大师,化工企业安全教育与应急演练的新助力

化工企业的生产安全培训,作为保障员工生命安全与企业稳定运营的基石,其重要性不言而喻。传统的培训方式内容僵化、形式单一缺乏互动、效果难以评估,越来越不适应化工企业的实际需求。因此,探索和应用更为高效、创新的培训工具&…

【Qt】实现顶部导航栏自适应滑动效果

需求: 顶部导航栏有若干选项,可能很多,顶部区域不能完全展示,比如10个选项,界面一次只能展示五个,那么要求把后面的选项隐藏起来,并且,当点击第四个第五个按钮的时候,自…

软件工程进度管理

答案:A D 解析: 由选项可以看出,有B,E,C,K,这里选择经过它们路径最长的就是正确答案 选项B 路线 ABIJL362819 路线 ABDIJL3522820 选项E 路线 AEGJL432817 路线 AEGHKL4334317 选项C 路线 ACFHKL5314316 选项D 路线 A…

【GBase 8c V5_3.0.0 分布式数据库常用维护命令】

一、查看数据库状态/检查(gbase用户) 1.gha_ctl monitor 使用gha_ctl monitor查看节点运行情况(跟dcs的地址和端口) gha_ctl monitor -c gbase -l http://172.20.10.8:2379 -Hall |coordinator | datanode | gtm | server|dcs:必选字段。指定查看哪类集…

Prometheus优化指南:如何提升系统性能

Prometheus 是一个强大的开源监控系统,它被广泛应用于云原生环境中,特别是在 Kubernetes 和其他容器化基础设施中。然而,随着监控数据量的增长,系统本身的性能可能会成为瓶颈。如果不进行优化,最终将影响到整体系统的可…

浏览器查消息

window.addEventListener(message,function(event){console.log(Received message,event.data)}); 并把弹窗口对准要接收消息的ifrme 发消息的窗口

大模型入门3:理解LLAMA

Model a stack of DecoderBlocks(SelfAttention, FeedForward, and RMSNorm) decoder block 整体结构:最大的区别在pre-norm x -> norm(x) -> attention() -> residual connect -> norm() -> ffn -> residual connect class DecoderBlock(nn.…

从零到一:构建你的第一个AI项目(实战教程)

引言 欢迎来到AI世界的初学者指南!在这个实战教程中,我们将一步步构建一个基础的AI项目,让你从零开始,亲手体验人工智能的魅力。我们的目标是让即使没有任何编程或AI背景的你,也能通过本教程完成一个小型的AI应用。今天…

《程序猿之设计模式实战 · 装饰者模式》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…

Python 求亲和数

亲和数(Amicable Numbers)是指两个不同的正整数,它们的真因数(即除去本身的所有因数)之和与对方的数相等。 def sum_of_proper_divisors(n):"""计算一个数的真因子之和"""divisors_su…

SpringBoot闲一品交易平台

SpringBoot闲一品交易平台 #vue项目实战 #计算机项目 #java项目 SpringBoot闲一品交易平台通过运用软件工程原理和开发方法,借助Spring Boot框架,旨在实现零食交易信息的高效管理,提升用户的购物体验和满意度。 技术栈 开发语言:…

用于安全研究的 Elastic Container Project

作者:来自 Elastic Andrew Pease•Colson Wilhoit•Derek Ditch 使用 Docker 启动 Elastic Stack 序言 Elastic Stack 是一个模块化数据分析生态系统。虽然这允许工程灵活性,但建立开发实例进行测试可能很麻烦。建立 Elastic Stack 的最简单方法是使用…

Day09-StatefuleSet控制器

Day09-StatefuleSet控制器 0、昨日内容回顾1、StatefulSets控制器1.1 StatefulSet概述1.2 StatefulSets控制器-网络唯一标识之headless1.3 StatefulSets控制器-独享存储 2、metric-server2.1 metric-server概述2.2 部署metric-server:2.3 hpa案例 3、helm概述3.1 安装helm3.2 h…

RabbitMQ 高级特性——持久化

文章目录 前言持久化交换机持久化队列持久化消息持久化 前言 前面我们学习了 RabbitMQ 的高级特性——消息确认,消息确认可以保证消息传输过程的稳定性,但是在保证了消息传输过程的稳定性之后,还存在着其他的问题,我们都知道消息…

【rpg像素角色】俯视角-行走动画

制作像素角色的俯视角行走动画并不像看上去那么复杂,尤其是在你已经完成了角色的4个方向站立姿势之后(其中左右方向可以通过水平翻转实现)。接下来,我会一步步为你讲解如何制作行走动画。 1. 理解行走规律 在制作行走动画之前&am…

Spring Boot集成Akka Stream快速入门Demo

1.什么是Akka Stream? Akka Streams是一个用于处理和传输元素序列的库。它建立在Akka Actors之上,使流的摄入和处理变得简单。由于它是建立在Akka Actors之上的,它为Akka现有的actor模型提供了一个更高层次的抽象。Akka流由3个主要部分组成-…

从0开始学习RocketMQ:快速部署启动

快速部署 快速部署一个单节点单副本 RocketMQ 服务,并完成简单的消息收发。 安装Apache RocketMQ 下载地址:RocketMQ官网下载 这里我们下载二进制包:rocketmq-all-5.3.0-bin-release.zip 直接解压即可:tar -zxvf rocketmq-all…