字符编码简述
一.基本概念
计算机存储的是二进制数据, 0/1 组成的比特, 我们在屏幕上看到的各种显示字符, 包括字母, 汉字, 数字, 各种符号等等, 都是由一串二进制比特转码之后得到的. 这种转码的规则就叫做字符编码. 例如最常见的 ASCII 规则: 字母'A': 对应二进制 0x41, 101000001.
二.ASCII
全称是American Standard Code for Information Interchange, 美国信息交换标准代码. 这是美国人设计的标准, 只支持基础拉丁字符. ASCII 的设计很简单, 用一个字节来表示一个字符, 最高位的取值永远为'0', 字符范围 0x00-0x7F, 一共包含了 128 个字符, man ascii可以在 Posix 中看到所有的 ASCII 字符集.
三.EASCII
Extended ASCII, 延伸美国标准信息交换码, 相比于 ASCII, EASCII 最高位不再限制为'0', 增加了 0x80-0xFF 的这一段. EASCII 扩充出来的符号包括表格符号, 计算符号, 希腊字母和特殊的拉丁符号, 基本解决了整个西欧的字符编码问题.
四.GB2312
国家标准简体中文字符集, 并在1981年5月开始在国内实行. GB2312 基于分区处理, 编码时采用2字节, 兼容 ASCII 编码, 高字节0xA1-0xF7, 低字节0xA1-0xFE, 高位都是'1', 所以能兼容 ASCII 编码. GB2312 字符集包含了 7445 个字符, 其中 6763 个汉字, 已经能满足基本需求.
五.GBK
GB2312 支持的汉字毕竟有限, 部分生僻汉字, 包括繁体字, 以及日语汉语等, 并未有收录在内. 于是微软利用 GB2312 未使用的编码空间, 收录 GB13000 中的全部字符制定了 GBK 编码, 最早实现于 Windows 95 简体中文版.
虽然 GBK 收录 GB13000 的全部字符, 但编码方式并不相同. GBK 编码最多使用 2 个字节: 字节为0x00-0x7F兼容 ASCII, 最高位为 1 的字节表示 2 字节编码, 高字节范围为0x81-0xFE, 低字节范围为0x80-0xFE. GBK 字符集一共支持 21886 个符号.
六.GB18030
GB18030, 全称: "国家标准 GB18030-2005《信息技术 中文编码字符集》", 是中国最新的内码字集, 是 "GB18030-2000《信息技术 信息交换用汉字编码字符集 基本集的扩充》"的修订版. 与 GB2312 完全兼容, 与 GBK 基本兼容, 支持 GB13000 及 Unicode 的全部统一汉字, 共收录汉字70244个. GB18030 采用多字节编码, 每个字符由1或2或4个字节进行编码.
七.BIG5
Big5, 又称为大五码或五大码, 共收录 13060 个汉字, 开始支持繁体中文. Big5 普及于台湾, 香港与澳门等繁体中文通行区, 但长期以来并非当地的国家标准, 而只是业界标准. Big5 是一套双字节字符集, 使用了双八码存储方法, 以两个字节来安放一个字: 高字节范围0x81-0xFE, 低字节范围0×40-0x7E, 及0xA1-0xFE.
八.Unicode
因为不同的语言采用不同的编码, 有可能导致冲突与不兼容性, 从而出现乱码现象. 为了解决这些局限, 国际标准化组织(ISO)发布了统一编码标准 Unicode, 采用4个字节表示一个字符, 这样理论上 Unicode 能表示的字符数就达到了 2^31 约 21 亿左右字符, 完全可以涵盖世界上一切语言所用的符号.
Unicode 是一种编码标准, 它的实现有很多种, 包括 UTF(Unicode Translation Format) 的 UTF8 和 UTF16, 上文提到的 GBK 和 GB18030 也是 Unicode 的实现.
九.UTF-8
上文提到, Unicode 对所有的字符编码均需要 4 字节, 对拉丁字母或汉字来说, 前2-3个字节是0, 非常浪费. 另外一个问题, 计算机怎么知道四个字节表示一个 Unicode 中的字符, 还是分别表示4个 ASCII 字符?
以上两个问题, 直至 UTF-8 作为 Unicode 的一种实现后, 才部分解决, 得以完成推广使用. UTF-8 的设计者叫 Ben Thomason, 据说是在餐巾纸上设计出来的. 关于 UTF-8 的基本规则, 阮一峰老师总结为两条:
规则1: 对于单字节字符, 字节的第一位为0, 后7位为这个符号的 Unicode 码, 所以兼容 ASCII.
规则2: 对于n字节的字符, 第一个字节前n位都设为1, 第n+1位为0, 后面字节的前两位一律设为10, 剩下没有提及的位, 全部为这个符号的 Unicode 编码。
原始码(16进制) UTF-8编码(二进制) 0000 − 007F 0 xxxxxxx 0080 − 07FF 110 xxxxx 10 xxxxxx 0800 − FFFF 1110 xxxx 10 xxxxxx 10 xxxxxx
1.ASCII码 0x00-0x7F, 编为 1 个字节的 UTF-8 码.
2.汉字的 Unicode 编码范围为 0x0800-0xFFFF, 所以被编为 3 个字节的 UTF-8 码.
一段根据 UTF-8 字符获得 Unicode 的 C 代码:
int _get_unicode(const char* str, int n) { int i; int unicode = str[0] & ((1 << (8-n)) - 1); for (i=1; i<n; i++) { unicode = unicode << 6 | ((uint8_t)str[i] & 0x3f); } return unicode; } int get_unicode(char** utf8, int* unicode) { uint8_t c; if (!utf8 || !(*utf8) || !unicode) { return -1; } if (**utf8 == 0) { return -1; } c = (*utf8)[0]; if ((c & 0x80) == 0) { *unicode = _get_unicode(*utf8, 1); *utf8 += 1; } else if ((c & 0xe0) == 0xc0) { *unicode = _get_unicode(*utf8, 2); *utf8 += 2; } else if ((c & 0xf0) == 0xe0) { *unicode = _get_unicode(*utf8, 3); *utf8 += 3; } else if ((c & 0xf8) == 0xf0) { *unicode = _get_unicode(*utf8, 4); *utf8 += 4; } else if ((c & 0xfc) == 0xf8) { *unicode = _get_unicode(*utf8, 5); *utf8 += 5; } else if ((c & 0xfe) == 0xfc) { *unicode = _get_unicode(*utf8, 6); *utf8 += 6; } else { return -1; } return 0; }
十.常见问题
1.Windows Notepad 中的编码 ANSI 保存选项, 代表什么含义?
ANSI 是 Windows 的默认的编码方式, 对于英文文件是 ASCII 编码, 对于简体中文文件是 GB2312 编码(只针对 Windows 简体中文版, 如果是繁体中文版会采用 Big5码). 所以, 如果将一个 UTF-8 编码的文件, 另存为 ANSI 的方式, 对于中文部分会产生乱码.
2.什么是 UTF-8 的 BOM?
BOM 的全称是Byte Order Mark, 又是微软这货搞出来的特殊东西, 在 UTF-8 编码的文件起始位置, 加入三个字节"EE BB BF", 用于标识文件.
文章来源:http://www.gaccob.com/publish/2012-09-07-encode.html#eascii
posted on 2018-10-21 15:32 bijian1013 阅读(459) 评论(0) 收藏 举报
浙公网安备 33010602011771号