硬汉嵌入式论坛

 找回密码
 立即注册
查看: 947|回复: 1
收起左侧

[其它] 字符编码简介:ASCII,Unicode 和 UTF-8

[复制链接]

78

主题

278

回帖

512

积分

金牌会员

积分
512
发表于 2024-10-8 17:02:42 | 显示全部楼层 |阅读模式
字符编码简介
1:ASCII
最初的计算机的使用是在美国,所用到的字符也就是现在键盘上的一些符号和少数儿个特殊的符号,一个字节所就能足以容纳所有的这些字符,实际上表示这些字符的字节最高位都为0,也就是说这些字节都在0到127之间,如字符a对应数字97。这套编码规则被称为ASCII(美国标准信息交换码)
  2:GBK、GB2312
随着计算机的应用和普及,许多国家都把本地的字符集引入了计算机,大大扩展了计算机中字符的范围。以中文为例,一个字节是不能容纳所有的中文汉字的,因此大陆将每一个中文字符都用两个字节的数字来表示,原有的ASCII字符的编码保持不变,仍用一个字节表示,为了将一个中文字符与两个ASCII码字符相区别,中文字符的每个字节的最高位都为1,这套编码规则称为GBK(国标码),后来,又在GBK的基础上对更多的中文字符(包括繁体)进行了编码,新的编码系统就是GB2312,可见GBK是GB2312的子集。
  3:Unicode
每个国家和地区都制定了一套自己的编码,那么同样的一个字节,在不同的国家和地区就代表了不同的字符。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (ג),在俄语编码中又会代表另一个符号。
为了解决各个国家和地区使用本地化字符编码带来的不利影响,将全世界所有的符号进行了统一编码,称之为Unicode编码。这是一种所有符号的编码。如 “中”这个符号,在全世界的任何角落始终对应的都是一个十六进制的数字4e2d。
最初的Unicode标准UCS-2使用两个字节表示一个字符,所以你常常可以听到Unicode使用两个字节表示一个字符的说法。但过了不久有人觉得256*256太少了,还是不够用,于是出现了UCS-4标准,它使用4个字节表示一个字符,不过我们用的最多的仍然是UCS-2。
  4:UTF
注意,UCS(Unicode Character Set)还仅仅是字符对应码位的一张表而已,比如"中"这个字的码位是4E2D。字符具体如何传输和储存则是由UTF(UCS Transformation Format)来负责。
一开始这事很简单,直接使用UCS的码位来保存,这就是UTF-16,比如,"汉"直接使用\x4E\x2D保存(UTF-16-BE),或是倒过来使用\x2D\x4E保存(UTF-16-LE)。
这里就有两个严重的问题,第一个问题是,如何才能区别Unicode和ASCII?计算机怎么知道两个字节表示一个符号,而不是分别表示两个符号呢?第二个问题是,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用两个字节表示,这对于存储来说是极大的浪费。于是UTF-8横空出世。
  5:UTF-8
UTF-8是使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8Unicode的实现方式之一
UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。UTF-8的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
下表总结了编码规则,字母x表示可用编码的位。
Unicode符号范围
  UTF-8编码方式
00 00 00 00   -   00 00 00 7F
  0xxxxxxx
00 00 00 80   -   00 00 07 FF
  110xxxxx 10xxxxxx
00 00 08 00   -   00 00 FF FF
  1110xxxx 10xxxxxx 10xxxxxx
00 01 00 00   -   00 10 FF FF
  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
跟据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
下面以汉字"严"为例,演示如何实现UTF-8编码。
已知"严"的unicode是4E25(1001110 00100101),根据上表,可以发现4E25处在第三行的范围内(00000800-0000 FFFF),因此"严"的UTF-8编码需要三个字节,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,"严"的UTF-8编码是"11100100 10111000 10100101",转换成十六进制就是E4B8A5。
  6:BOM
BOM(Byte Order Mark)。UTF引入了BOM来表示自身编码,如果一开始读入的几个字节是其中之一,则代表接下来要读取的文字使用的编码是相应的编码:
BOM_UTF8             '\xef\xbb\xbf'
BOM_UTF16_LE    '\xff\xfe'
BOM_UTF16_BE    '\xfe\xff'
如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。以汉字"严"为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,就是Big endian方式;25在前,4E在后,就是Little endian方式。
          一般情况下,不建议在Linux中使用BOM。
7:Unicode与UTF-8之间的转换
"严"的Unicode码是4E25,UTF-8编码是E4B8A5,以该汉字为例,利用Ultraedit查看各种编码的具体值,一般的编辑器都支持以不同的编码方式保存文本,编码方式如下:
1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。这种方式编码的文件,就是两个字节"D1 CF",这正是"严"的GB2312编码:
190e38b8f52adf8cb34b13db41951c40.png
2)UTF16编码指的是UCS-2编码方式,即直接用两个字节存入字符的Unicode码。编码是四个字节"FF FE 25 4E",其中"FF FE"表明是小头方式存储:
2.png
3)UTF16-NOBOM编码与上一个选项相对应,只不过没有BOM编码,也就是文件中只存储UTF16编码"25 4E":
3.png
4)UTF-8编码,文件中共6个字节:"EF BB BF E4 B8 A5",其中前三个为BOM编码,后三个为UTF8编码:
4.png
5)UTF8-NOBOM编码与上一个选项相对应,只不过没有BOM编码,也就是文件中只存储UTF8编码" E4 B8 A5":
5.png

另附参考链接:
http://www.ruanyifeng.com/blog/2 ... code_and_utf-8.html



回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2024-10-9 10:12:46 | 显示全部楼层
谢谢分享。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-13 06:10 , Processed in 0.052621 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表