IMX6ULL —— 字符编码方式和实现

简介: IMX6ULL —— 字符编码方式和实现

前言:

使用的开发板韦东山老师的 IMX6ULL

字符的编码方式

编码与字体

在计算机上,我们看到的字符“A”可能长这样:

也可能长这样:


对于同一个 TXT 文件中的内容,你在 Notepad 上选择不同字体时,字符显示的形状不一样。


所以 TXT 文件中保存的是字符的核心:它的编码值。而 Notepad 上显示时, 这些字符对应什么样的形状态,这是由字符文件决定的。编码值,字体是两个不一样的东西,比如 A 的编码值是 0x41,但是在屏幕上显示出来时可以使用不同的形状。


什么叫编码?


就是一个字符用什么数字来表示。在计算机里一切都是用数字 来表示,比如字符 A,用 0x01 还是 0x02 来表示它?我们使用 0x41 来表示它。 当你去打开一个 TXT 文件时,发现里面含有数值 0x41,你就知道了:哦,这里 有一个字符 A。


1.ASCII

是“American Standard Code for Information Interchange”的缩 写,美国信息交换标准代码。


电脑毕竟是西方人发明的,他们常用字母就 26 个,区分大小写、加上标点符号也没超过 127 个,每个字符用一个字节来表示就足够了。一个字节的 7 位就 可以表示 128 个数值,在 ASCII 码中最高位永远是 0。


字符和数值的对应关系百度百科-验证

部分如下:

2.ANSI

使用记事本保存文件时,可以选择“ANSI”编码,却没有“ASCII”,怎么回事?

ASNI 是 ASCII 的扩展,向下包含 ASCII。


对于 ASCII 字符仍以一个字节来表示,对于非 ASCII 字符则使用 2 字节来表示。并没有固定的 ASNI 编码,它跟 “本地化”(locale)密切相关。比如在中国大陆地区,ANSI 的默认编码是 GB2312; 在港澳台地区默认编码是 BIG5。以数值“0xd0d6”为例,对于 GB2312 编码它表示“中”;对于 BIG5 编码它表示“笢”。所以对于 ANSI 编码的 TXT 文件,如果你打开它发现乱码,那么还得再次细分它的具体编码。


比如对于一个 TXT 文件,里面的数值如下:

4fccb8d9f016b067c8524a371855691e_d21474d5ae9340a8ac11fe2ba78178d8.png

使用 Notepad 打开后,选择不同的编码(或称为字符集),有不一样的显示, 如下:


a1e8b46c839e5cf36ab5e2ce09020a39_bd37b09d6e3546bfbe80d1af44f57ee9.png


这仅仅是在中国地区就出现这些不兼容的问题。对于不同国家,它们默认的 ANSI 编码各不相同,所以同一个 TXT 文件在不同国家就很有可能出现乱码。 根本的原理在于没有“统一的编码”,那解决方法自然就是使用“统一的编 码”:UNICODE。


3.UNICODE


在 ANSI 标准中,很多种文字都有自己的编码标准,汉字简体字有 GB2312、 繁体字有 BIG5,这难免同一个数值对应不同字符。比如数值“0xd0d6”,对于 GB2312 编码它表示“中”;对于 BIG5 编码它表示“笢”。这造成了使用 ANSI 编 码保存的文件,不适合跨地区交流。


UNICODE 编码就是解决这类问题:对于地球上任意一个字符,都给它一个唯一的数值。 UNICODE 仍然向下兼容 ASCII,但是对于其他字符会有对应的数值,比如对 于“中”、“笢”,它们的数值分别是:0x4e2d、0x7b22


UNICODE 中的数值范围是 0x0000 至 0x10FFFF,有 1,114,111 即 100 多万个数值,可以表示 100 多万个字符,足够我们使用了。


UNICODE 编码实现

所谓编码实现,就是对于一个数值,怎么表示它。这很奇怪,数值还能怎么表示?


比如“中”的 UNICODE 值是 0x4e2d,在 TXT 文件中怎么表示 0x4e2d? 直接写入 0x4e2d?不行!


比如在 TXT 文件中写入 2 字节数据“0x2d 0x4e”,它可以用来表示“中” 字吗?不能!它们对应 ASCII 字符“-N”。


问题的关键在于:怎么断字。在 TXT 文件中,2 字节数据“0x2d 0x4e”是作为一个整体看待,还是拆成 2 部分看待?


所以,需要用一定的技巧来表示数值,这就对应不同的编码实现。


现在我们知道:


  • ASCII 编码中使用一个字节来表示一个字符,只用到其中的 7 位,最高位恒为 0;
  • ANSI 编码中,对于 ASCII 字符仍使用一个字节来表示(BIT7 是 0),对于非 ASCII 字符一般使用 2 个字节来表示,非 ASCII 字符的数值 BIT7 都是 1。

UNICODE:比较复杂


先用记事本新建 3 个文件:utf-16_le.txt、utf-16_be.txt、utf-8.txt、 bom_utf-8.txt,里面的内容都是“ab 中”,保存时编码分别选择“UTF-16 LE”、 “UTF-16 BE”、“UTF-8”、“带有 BOM 的 UTF-8”

怎么表示一个 UNICODE 数值?

1.使用 3 个字节表示一个 UNICODE

不,太浪费。

UNICODE 的最大值是 0x10FFFF,那使用 3 个字节来表示一个 UNICODE 数 值?这当然是很省事的方法,但是会造成浪费,比如字符 A 的 UNICOCDE 值是 0x41,难道也用“0x41 0x00 0x00”这 3 个字节来表示?


2.UCS-2 Little endian/UTF-16 LE

每个 UNICODE 值用 3 字节来表示有点浪费,那只用 2 字节呢?它可以表示 2^16=65536 个字符,全世界常用的字符都可以表示了。


Little endian 表示小字节序,数值中权重低的字节放在前面,比如字符 “A 中”在 TXT 文件中的数值如下,其中的“A”使用“0x41 0x00”两字节表 示;“中”使用“0x2d 0x4e”两字节表示。文件开头的“0xff 0xfe”表示“UTF-16 LE

c641b927a7d0d4c1e5d9db7e3677ef7e_31d0f9606bc84aaeb0c6f0cf0a715f12.png

3.UCS-2 Big endian/UTF-16 BE

Big endian 表示大字节序,数值中权重低的字节放在后面,比如字符“ab 中”在 TXT 文件中的数值如下,其中的“A”使用“0x00 0x41”两字节表示; “中”使用“0x4e 0x2d”两字节表示。文件开头的“0xfe 0xff”表示“UTF-16 BE

f0e37bdc1168437ea6cbe60983074dc4_f200ba480aa74ab29b532eb26229075d.png

4.UTF8

在上面 2 种方法中,每一个 UNICODE 使用 2 字节来表示,这有 3 个缺点: 表示的字符数量有限、对于 ASCII 字符有空间浪费、如果文件中有某个字节丢 失,这会使得后面所有字符都因为错位而无法显示。 使用 UTF8 可以解决上述所有问题。UTF8 是变长的编码方法,有 2 种 UTF8 格式的文件:带有头部、不带头部。先举例,看图对于其中的 ASCII 字符,在 UTF8 文件中直接用其 ASCII 码来表示,比如上图中的 0x61 表示字符 a、0x62 表示字符 b。上图中的 3 个字节“0xe4 0xb8 0xad”表示的数值是 0x4e2d,对应“中”的 UNICODE 码。

188717083d70206f75cbed5df04e5ac4_061a58b80e2745a3bd0cff057a0c5172.png

对于非 ASCII 字符,使用变长的编码:每一个字节的高位都自带长度信息。

e08260ee3457f5d45e0c029d2d1727e2_a615ed6a358b41a592c8cbc45d6bfeab.png

上图中,0xe4 的二进制是“11100100”,高位有 3 个 1,表示从当前字节起 有 3 字节参与表示 UNICODE;


0xb8 的二进制是“10111000”,高位有 1 个 1,表示从当前字节起有 1 字节 参与表示 UNICODE;


0xad 的二进制是“10101101”,高位有 1 个 1,表示从当前字节起有 1 字节 参与表示 UNICODE;


除去高位的“1110”、“10”、“10”后,剩下的二进制数组合起来得到 “01001110001101”,它就是 0x4e2d,即“中”的 UNICODE 值。


使用 UTF8 编码时,即使 TXT 文件中丢失了某些数据,也只会影响到当前字符的显示,后面的字符不受影响。

相关文章
|
7月前
|
传感器 存储 运维
161216-01 | Bently Nevada |以太网10BASE-T/100BASE-TX I/O模块
Bentley Nevada的161216-01是款以太网I/O模块,支持10BASE-T/100BASE-TX,用于机械保护监测。具备多通道输入,兼容多种信号类型,保证高可靠性和灵活性。模块带有前板LED指示运行状态和通信情况,具有可编程性及故障保护功能,适应-30°C至+65°C的工作温度。适用于复杂工业环境,确保系统安全运行。如需详细信息,可进一步咨询。
161216-01 | Bently Nevada |以太网10BASE-T/100BASE-TX  I/O模块
|
7月前
|
Linux 内存技术
设备树知识小全(七):地址编码
设备树知识小全(七):地址编码
111 0
|
存储 自然语言处理 编译器
BIT-7文件操作和程序环境(16000字详解)
BIT-7文件操作和程序环境(16000字详解)
88 0
|
编译器 C++
驱动开发:内核PE结构VA与FOA转换
本章将继续探索内核中解析PE文件的相关内容,PE文件中FOA与VA,RVA之间的转换也是很重要的,所谓的FOA是文件中的地址,VA则是内存装入后的虚拟地址,RVA是内存基址与当前地址的相对偏移,本章还是需要用到`《驱动开发:内核解析PE结构导出表》`中所封装的`KernelMapFile()`映射函数,在映射后对其PE格式进行相应的解析,并实现转换函数。
247 0
|
安全
[oeasy]python0 113_字符编码_VT100控制码_iso_8859_1_拉丁字符_latin
[oeasy]python0 113_字符编码_VT100控制码_iso_8859_1_拉丁字符_latin
149 0
[oeasy]python0 113_字符编码_VT100控制码_iso_8859_1_拉丁字符_latin
|
编解码 数据安全/隐私保护 Python
Python 技术篇 - 修改pyminifier库源码解决编码不一致导致的报错问题:‘gbk‘ codec can‘t decode byte 0x80 in position 54
Python 技术篇 - 修改pyminifier库源码解决编码不一致导致的报错问题:‘gbk‘ codec can‘t decode byte 0x80 in position 54
434 0
Python 技术篇 - 修改pyminifier库源码解决编码不一致导致的报错问题:‘gbk‘ codec can‘t decode byte 0x80 in position 54
|
程序员 Python
codecs模块-完成字符编码
字符的编码是按照某种规则在单字节字符和多字节字符之间进行转换的某种方法。从单字节到多字节叫做decoding,从多字节到单字节叫做encoding。在这些规则中经常用到的无非是UTF-8和GB2312两种。
199 0
|
开发工具
新增2款开发工具:base64编码解码,unicode编码解码
最近由于工作需要,制定了一份底层通信协议,为了保证协议顺利传输任意内容,规定数据段必须采用base64编码,来规避其他字符对于协议解析的影响。然后就顺手为本站新增2款开发人员工具。 base64编码解码 体验地址:https://www.opengps.cn/Tools/Base64/Index.aspx unicode编码解码 体验地址:https://www.opengps.cn/Tools/Unicode/Index.aspx 原文地址: https://www.opengps.cn/Blog/View.aspx?id=382 文章的更新编辑依此链接为准。
1306 0