「MISC」字符编码 - ASCII, EASCII, ANSI, EUC, GBK, Unicode, UTF-8

2023-10-14 13:20

本文主要是介绍「MISC」字符编码 - ASCII, EASCII, ANSI, EUC, GBK, Unicode, UTF-8,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

编程的过程当中,不免会碰到一些关于编码的问题,其中对于使用简体中文的中国人来说最常见的就是 UTF-8GBK
大部分的时候都能够使用语言内置的转换函数或者一些库来进行编码的检测和转码,但是当出现一些乱码的时候,往往有些不知所措,不知道为什么会出现这样的码点,也不知如何去解决它。这主要是由于对编码方式的极度不了解。但如果知道不同的格式是如何编码的,程序是如何解析的,那么乱码的问题便不是问题。

下面会对 ASCII, EASCII, ANSI, EUC, GB2312, GBK, UNICODE, UTF-8 和与之相关的一些术语进行解释,相关的编码方式进行阐述,从根本上解决让人头疼的编码问题。

ASCII

ASCII - American Standard Code for Information Interchange

古老(1967)的编码方式,也是最简单的编码方式,使用 7 bits 囊括了26个基本拉丁字母、阿拉伯数字、常用英文标点符合和彼时常用的控制字符,但现在大部分的ASCII控制字符都已经被废弃使用。
简单的编码会让编码解码变得简单,但是缺点也显而易见——它无法满足其他语言的编码需求。

下图是 ISO/IEC 646 定义的标准的 ASCII 7 bits 码表,其允许各国对除了英文字母和数字的其他部分修改,以满足本国需求。
ISO/IEC 646

EASCII

EASCII - Extended American Standard Code for Information Interchange

EASCII 顾名思义,其在ASCII的基础上拓展了1 bit,总共达到了8 bits,可以多显示128个字符。
EASCII 编码方式比较混乱,在不同的平台和协议上经常不相同,但我们主要接触到的有两种:ISO/IEC 8859-1 (Latin-1),Code page 437。

在这里有必要补充说明一下什么是代码页(Code page)
代码页是windows上命令行中的编码表,不同的代码页标识着不同的编码方式,下面是其中一些代码页编号对应的编码方式:

  • 437: OEM United States

  • 1252: ANSI Latin 1; Western European (Windows)

  • 65001: Unicode (UTF-8)

  • 936: ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312); GBK

  • ...

其中代码页1252与 ISO/IEC 8859-1 (Latin-1)基本一致,以下两图分别为代码页1252和代码页437:

Code page 1252
Code page 437

Windows全部的代码页对应表可以查看 https://msdn.microsoft.com/en...

ANSI

ANSI - American National Standards Institute

这个名称的来历,是一个非常长的故事。我们现在说的,经常看到的一般都是Window的记事本另存为里面的ANSI编码。

它确实是ANSI这个机构所发布的 8-bit 编码标准(虽然基本上是抄 ISO 8859)。但是微软使用编码标准的时候没有注意到其实ANSI是一套标准,仅仅将它表示Latin-1。
后来逐步的,Windows的国际版本越来越多。现在,Windows上面的ANSI编码代表的是操作系统本地的默认代码页,例如在中文版Windows10上就指的是GBK。

许多文章说 GBK、BIG-5 是属于ANSI编码的,其实不对。

EUC

EUC - Extended Unix Code

EUC 是一个符合 ISO 2022 标准的 8-bit 的编码方法。
EUC 定义了4个码集:

  • CS0:ASCII 7 bits编码标准,即 ISO 646;一个字节

  • CS1: MSB(最高有效位)必须为1,0xA0-0xFF;任意字节数

  • CS2: MSB必须为1,第一个字节必须为0x8E,0xA0-0xFF;任意字节数

  • CS3: MSB必须为1,第一个字节必须为0x8F,0xA0-0xFF;任意字节数

CS1,CS2,CS3规定范围在0xA0-0xFF其实是为了兼容 ISO 2022

每个码集中都要满足如下条件:

  • 码集中每个字符都需要使用 相同的字节数

  • 码集中每个字符在等宽终端中都显示相同的宽度

也就是说,我决定将某些字符用CS1中的码来编码,那么这些落在CS1中的字符必须全部是一个、两个、三个、... 、N个字节,不允许在同一个码集的字符有些是一个字节,有些又是其他数量的字节。

GB2312, GBK

GB - 国标

    • 扩(展)

GB2312又称GB0,是EUC的一种实现,它只使用了CS1,并且规定CS1为两个字节。
上面已经详细的介绍了EUC,那么GB2312的编码方式也非常明朗了。遇到MSB为0的,则读取一个字节;而遇到MSB为1的,则读取两个字节。

抛开具体的字节编码,来看GB2312的设计思路:
它一共分为81个区:

  • 01-09:特殊符号

  • 16-55:一级汉字(常用汉字),拼音排序

  • 56-87:二级汉字(非常用汉字),部首/笔画排序

其中10-15,88-94区未有编码,每个区(从1开始编号)有94(区号 + 0xA0)个字;所以第一个汉字的编码就是(0xA0 + 16) + (0xA0 + 1) = 0xB0A1

关于GBK就不解释太多,只需要知道GBK是GB2312的拓展,向后兼容。

Unicode

Unicode - 一种能够囊括所有字符的编码标准

Unicode分为(0-16)平面+16位编码空间,大部分的常用语言的常用字符都落在0平面内,也就是0x0000-0xFFFF。
为了向前兼容,Unicode的前256个字符为上面说的ISO标准 8-bit 标准(ISO 8859-1

0 平面也称为基本多文种平面(BMP),各个平面的用途如下:

Unicode平面映射表

Wikipedia - Unicode字符平面映射

ʕ•̀ω•́ʔ✧ 就是这么简单,不比上面各个编码如此复杂

UTF-8

UTF-8 - 8-bit Unicode Transformation Format

既然已经有了编码标准了,接下来就要考虑的就是怎么样把它存到计算机里了。
如果严格的按照Unicode的标准(UTF-32)来存储的话,平面编号占两个字节,编码空间占两个字节,那么不管是只需要7bits的ASCII码抑或是可以用两个字节来表示的常用中文,就都得占据四个字节,未免也太浪费(内存、储存空间和带宽资源等)了。

UTF-8是一种变长储存的编码实现方式,对于不同的字符用1~6个字节来表示。
因为是变长,所以计算机如何区分一个字符是几个字节呢?规则如下:

  • ASCII码范围(0x00-0x7F),使用一个字节表示

  • 超过以上范围的,第一个字节的连续前多少位是1就表示这个字符使用几个字节,例如第一个字节为 0b1110xxxx 就表示包括这个字节在内的,接下来三个字节表示此字符。

UTF-8 储存格式

其实上面这张图我认为将后面6列放到最前面比较合适,但是摆到后面比较好看

可以看到,上面的 x 代表的是有效储存位,其他的都是用来起标识作用的。那么我们的中文到底占几个字节呢?
查表可知,常用汉字的Unicode编码落在基本多文种平面的0x4E00-0x9FFF(中日韩统一表意文字),即三个字节。

认真的人看到这里肯定会有一个疑问,为什么多字节字符除了第一个字节以外,后面的字节还是要以0b10开头呢?

让我们把目光放到上图,可以看到第一个字节没有以0b10开头的。如果后面的字节使用了全部的空间,程序每次定位一个位置都要从头开始查找,因为程序并不知道当前这个字节是否是第一个字节;而如果使用0b10作为开头的话,程序只需要向前查找不是0b10开头的字节,就可以知道它是当前字符的起始字节。

BOM

BOM - Byte-order Mark

由于UTF-16和UTF-32是定长编码,所以在编码单元里面存在大端和小端储存的问题,所以制定了以下规则来标识文件:

UTF BOM 映射表

虽然UTF-8这种变长的编码方式不存在大端小端的问题,但是还是指定了BOM来表示这个文件是UTF-8。在实际的使用过程当中尽量不要对UTF-8添加BOM,否则很多软件解析都会出现问题。

之后遇到文件前有两个或者三个不知道是什么的字节的时候就不用惊慌了。

  • 为什么 UTF-8 没有字节序,UTF-1 6和 UTF-32 有字节序?

  • 大端模式和小端模式

编码检测

一直以来都对 notepad++ 等一干智能编辑器如何自动检测文件编码非常好奇,趁此机会查了下资料。

基本上所有的编码检测都不是完全可靠的,都是根据字节的模式统计分析来确定最可能的编码,so~
其中能被最可靠的探测到的编码就是UTF-8了,根据上文,UTF-8有大量的0b10xxxxxx以及首字节的定式编码,所以一般来说不是很容易被检测错误。


✧⁺⸜(●˙▾˙●)⸝⁺✧ 写了一个月的文章完结撒花 ✧⁺⸜(●˙▾˙●)⸝⁺✧

这篇关于「MISC」字符编码 - ASCII, EASCII, ANSI, EUC, GBK, Unicode, UTF-8的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/210775

相关文章

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

form表单提交编码的问题

浏览器在form提交后,会生成一个HTTP的头部信息"content-type",标准规定其形式为Content-type: application/x-www-form-urlencoded; charset=UTF-8        那么我们如果需要修改编码,不使用默认的,那么可以如下这样操作修改编码,来满足需求: hmtl代码:   <meta http-equiv="Conte

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

如何将一个文件里不包含某个字符的行输出到另一个文件?

第一种: grep -v 'string' filename > newfilenamegrep -v 'string' filename >> newfilename 第二种: sed -n '/string/!'p filename > newfilenamesed -n '/string/!'p filename >> newfilename

如何导入sun.misc.BASE64Encoder和sum.misc.BASE64Decoder

右击项目名--->Build Path--->Configure Build Path...--->java Build Path--->Access rules:1 rule defined,added to all librar...   --->Edit --->Add...

4-4.Andorid Camera 之简化编码模板(获取摄像头 ID、选择最优预览尺寸)

一、Camera 简化思路 在 Camera 的开发中,其实我们通常只关注打开相机、图像预览和关闭相机,其他的步骤我们不应该花费太多的精力 为此,应该提供一个工具类,它有处理相机的一些基本工具方法,包括获取摄像头 ID、选择最优预览尺寸以及打印相机参数信息 二、Camera 工具类 CameraIdResult.java public class CameraIdResult {

【Python 千题 —— 算法篇】字符统计

Python 千题持续更新中 …… 脑图地址 👉:⭐https://twilight-fanyi.gitee.io/mind-map/Python千题.html⭐ 题目背景 在编程中,对字符串的字符统计是一个常见任务。这在文本处理、数据分析、词频统计、自然语言处理等领域有广泛应用。无论是统计字母出现的频率,还是分析不同字符类型的数量,字符串字符统计都是非常有用的技术。 字符统