编码-字符集-字符编码-code page-内码-big_endia-little_endian

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18218335/article/details/85331759

编码的直接感受

“汉”字的不同编码的文件存储数据:

编码方式 16进制
GBK2312 BA BA
unicode FF FE 49 6C
unicode-big-endian FE FF 6C 49
utf-8 EF BB BF E6 B1 89

Unicode、Unicode big endian和UTF-8编码的txt文件的开头会多出几个字节,分别是FF、FE(Unicode),FE、FF(Unicode big endian),EF、BB、BF(UTF-8)

如上所示,它们用来标识,文件的格式。当然, 这些字节序列,在字符集中是没有对应的字符的,否则,也就做不了标识符。
我们先解决一个可能很多人都有的疑问,上面的unicode 和 unicode-big-endian 无论是名字还是具体的16 进制表示上都十分相似,它们的关系是什么?之后我们再讨论,编码是什么,编码字符集是什么等问题。

0、big endian和little endian

big endian和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时,究竟是将6C写在前面,还是将49写在前面?如果将6C写在前面,就是big endian。如果将49写在前面,就是little endian。

“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,一个皇帝送了命,另一个丢了王位。

我们一般将endian翻译成“字节序”,将big endian和little endian称作“大尾”和“小尾”。
上面的段落引用了该文章:http://www.fmddlmyy.cn/text6.html

下面介绍编码和编码字符集:

字符集

我们看到的字符,和计算机中存储的二进制流的映射关系,需要一个表/映射/字典。这个,映射关系就称为字符集。如最开始的“汉”字,在不同的字符集中的映射。计算机逐步发展,逐步按需求支持不同语言(最开始是英语,ASCII字符集),因此,产生了很多字符集。当然,后面的版本大多是向下兼容的(比如,GBK 兼容GBK2312)。
常用的字符集有:

字符集 语言 描述
ASCII 英语 最开始的字符集
ISO-8859-1 英语、加一些字母及符号 ASCII 基础上,在空置的0xA0-0xFF的范围内,加入96 个字母及符号,以供使用附加符号和拉丁字母语言使用
GB2312 简体中文 1981年制定,7445 个图形文字,6763个汉字,对汉字进行“分区”处理,每区94 个汉字/符号,0~09 区为特殊符号,16~55区为一级汉字,按拼音排序
BIG5 繁体中文 1984 年台湾,13,053 个中文字
GB18030 汉字、日文假名、朝鲜语和中国少数民族文字 编码空间超过150 万个编码位,收录了27484个汉字,与Unicode3.0 版本兼容
Unicode 所有语言 1994年公布,最新为2012 年1月31日的Unicode 6.1 ,它为每种语言中的每个字符设定了统一且唯一的二进制编码,满足跨语言、跨平台进行文本转换、处理的要求,学名为UCS(Universal multiple-object coded character set、Unicode character set 的缩写),Unicode 只规定如何编码,没有规定如何传输、保存这个编码,(UTF-8、UTF-7、UTF-16都是广泛接受的方案、UTF-8好处是它与ISO-8859-1完全兼容)
UTF-8 Unicode 的一个使用方式 Unicode Transformation Format 即把Unicode 转做某种格式,是一种针对Unicode 的可变长度字符编码(1到6个字节)便于不同计算机之间使用网络传输不同语言和编码文字,使得双字节的Unicode能够在现存的处理单字节的系统上正确传输
UTF-16、UTF-32 所有语言 UTF-16 使用1个或2个未分配的16位代码单元的序列对Unicode 代码点进行编码,UTF-32 即将每一个Unicode 代码带你表示为相同值的32 位整数

字符集中包含什么

字符集就是一个规则的名字,使用中,需要用到三个关键元素:
字库表(character repertoire)、编码字符表(coded character set)、字符编码(character encoding form)。

  • 字库表,一个相当于所有可读或者可显示字符的 数据库,字库表决定了整个字符集能够展示表示的所有字符的范围。
  • 编码字符集,用一个编码值(code point)来表示一个字符在字库中的位置
  • 字符编码,将编码字符集和实际存储数值之间的转换关系,一般来说,都会直接将code point 的值作为编码后的值直接存储。比如,ASCII 中A 在表中排第65 位,而编码后A 的数值是*0100 0001** 。

字符编码的必要性

节省空间
上面的UTF-8 就是,Unicode 的一个字符编码形式,它的最小编码单位为一个字节。一个字节的前1-3 bit 为描述性比分,后面为实际序号部分。

  • 如果一个自己的第一位为0,表示当前为单字节字符,占用一个字节的空间,0 之后的所有部分(7-bit)代表在Unicode 中的序号
  • 110 开头,双字节,110 之后5bit + 后一个字节的除10 外的部分(6-bit)代表在unicode 中的需要,且第二个字节以10 开头
  • 1110,三字节,3bit+110外的5bit + 后两个字节的除10 外的部分(12bit=6+6)代表在unicode 中的序号
  • 10 开头,代表当前字节为多字节字符的第二个字节,10 之后的所有部分和之前的部分一同组成在Unicode 中的序号
实际字符 在Unicode字库序号的十六进制 在Unicode字库序号的二进制 UTF-8编码后的二进制 UTF-8编码后的十六进制
$ 0024 010 0100 0010 0100
¢ 00A2 000 1010 0010 1100 0010 1010 0010 C2 A2
20AC 0010 0000 1010 1100 1110 0010 1000 0010 1010 1100 E2 82 AC

以上信息参考:http://cenalulu.github.io/linux/character-encoding/

内码

内码指的是“将资讯编码后,透过某种方式储存在特定记忆装置时,装置内部的编码形式。

字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码

在以往的英文系统中,内码为ASCII。 在繁体中文系统中,目前常用的内码为大五码。在简体中文系统中,内码则为国标码。

为了软件开发方便,如国际化与本地化,现在许多系统会使用Unicode做为内码,常见的操作系统Windows、Mac OS X、Linux皆如此。许多编程语言也采用Unicode为内码,如Java、Python 3。

code page

目前Windows的内核已经支持Unicode字符集,这样在内核上可以支持全世界所有的语言文字。但是由于现有的大量程序和文档都采用了某种特定语言的编码,例如GBK,Windows不可能不支持现有的编码,而全部改用Unicode。
Windows使用代码页(code page)来适应各个国家和地区。code page可以被理解为前面提到的内码。GBK对应的code page是CP936。微软也为GB18030定义了code page:CP54936
现在的Windows在系统内部支持Unicode,然后用代码页适应各种语言,“内码”的概念就比较模糊了。微软一般将缺省代码页指定的编码说成是内码。

Windows的内码是Unicode,它在技术上可以同时支持多个代码页。只要文件能说明自己使用什么编码,用户又安装了对应的代码页,Windows就能正确显示,例如在HTML文件中就可以指定charset。

windows 中对code page 的描述

https://docs.microsoft.com/en-us/windows/desktop/intl/code-pages
每个code page 由一个code page id 标识,如,1252 unicode。id 列表:https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers。

windows code page,通常称为“ANSI 代码页”,是非ASCII 值(大于127的值)代表国际字符的code page。这些code page 在windows me 中本机使用,也可以在windows NT 及更高版本上使用。

许多windows api 有A 版本 和 W 版本,A 版本基于windows code page 处理text,W 版本处理unicode。

  • windows code pages 也被称作 “active code pages ”或 “system active code pages”,一个windows 操作系统总是有一个当前的active windows code page。所有的 ANSI 版本 API 使用current active code page。

  • OEM code pages,其中,非ASCII 的部分,用来标识线和标点字符。这些codee page 原来用于MS-DOS,现在也在console app 中。它们也被用在FAT12、FAT16、FAT32 等文件系统的非扩展文件名中,https://docs.microsoft.com/en-us/windows/desktop/intl/character-sets-used-in-file-names 对此有描述。通常的英文 OEM code page 为code page 437.

windows code pages 和 OEM code pages中,code value 0x00 到 0x7F 对应于7-bit ASCII 字符集。0x00~0x19 及 0x7F 表示标准控制字符,0x20 到 0x7E 表示标准可显示字符。剩下的,0x80到0xFF,随着字符集不同而不同。每个字符集包括不同的特殊字符,通常是为一种语言或一组语言定制的。windows code page 1252 和 OEM code page 437 通常用在US。

除了windows 和OEM code pages,你的app 可以使用非原生code pages。
两种unicode 编码(UTF-7 和 UTF-8)被实现为code pages。像其他code page一样,使用code page id,可用许多相同的unicode 和 character set api 进行处理。

code pages 可以是single-byte character set pages 和 double-byte character set。在SBCS pages 中,每个byte 直接编码一个单独的字符,因此,它可能表示256 个不同的字符。DBCS code pages 被用来表示日语和中文等语言。在这种code page 结构下,某些字符具有双字节编码,其中某些字节值(始终值大于127)充当“前导字节”。前导字节只能与“跟踪字节”一起映射到字符,而不是自己编码字符。
某些传统协议需要使用SBCS和DBCS代码页。每个SBCS / DBCS代码页支持不同的字符,但是没有代码页支持Unicode提供的全部字符。每个SBCS / DBCS代码页支持不同编码的不同子集。

除了SBCS 和 DBCS code pages,你的应用程序可以使用多字节字符集code pages,52936, 54936, 51949, 和5022,它使用类似于DBCS 的方法,虽然多字节字符集code pages 超出了某些字符的双字节编码。UTF-7 和 UTF-8 使用类似的方法分别基于7-bit 和 8-bit 字节对unicode 进行编码。更多信息,请参阅:https://docs.microsoft.com/en-us/windows/desktop/intl/unicode

一些unicode 和 字符集函数允许你的app 来应对code pages。一个app 可以使用GetCPInfo 和 GetCPInfoEx 函数得到一个code page 的信息。这个信息包括,当一个被转换的string 中的一个字符在code page 中没有对应的项的时候的默认字符。

一个app 可以使用multibytetowidechar 和 widechartomultibyte 函数在基于windows code pages 和unicode strings 的strings 之间转换。尽管称为“Multibyte”,这些函数,在SBCS、DBCS 和multibyte character set code pages 上是一样的。

你的app 可以使用C runtime library 函数在windows code pages 和 OEM code pages 之间转换,但是,使用这些函数需要担一定的丢失数据的风险,因为它们的字符集并不完全匹配。

你的app 可以使用GetACP 函数,解析当前windows code page 的ID。

猜你喜欢

转载自blog.csdn.net/qq_18218335/article/details/85331759