基础知识
在计算机的内部,信息都是以 二进制 的方式存储的,二进制的一 位(bit) 可以表示0和1。位也叫做 比特 。
位作为单位太小,为了便于使用,通常使用 字节(byte) 来表示二进制。 一个字节有8位 ,可以表示256种(2的8次方)种状态,对应数字是0~255。 字节是计算机存储的最小单位 。
计算机在存储各种类型的数据,文本,图像,音乐,视频等时,需要将数据转换成字节,这个过程就是 编码 。不同的格式有不同的编码,文本编码就是将文本转换成字节一种方法。下面,就来了解一下最简单的文本编码。
英文的编码
英文字母只有26个,大小写一共52个,数字有10个,再加上一些标点符号,也不超过256种,因此英文使用一个字节就可以表示。
计算机中最常见英文编码的就是 ASCII (American Standard Code for Information Interchange)美国信息标准信息交换码。
标准的ASCII编码使用7位。其中65~90是大写字母,97~122是小写字母,48~57是数字,32是空格。
扩展的ASCII使用了8位,增加了最高位为1的部分,用于表示特殊符号、外来语字母和图形符号。
小技巧:在电脑上,按住Alt键,使用小键盘区的数字按下ASCII编码,再松开Alt键,可以输入对应的字符了。
中文的编码
汉字的数量和英文字母相比,就不是一个量级了。中文常用字就有几千,使用一个字节无法表示。
汉字使用的编码是GB2312,一个汉字使用两个字节表示,比如”我”使用两个字节”CE D2″表示。
GB2312编码中,英文使用一个字节表示,兼容ASCII标准编码,字节的最高位为0;中文使用两个字节表示,每个字节的最高位都是1。
GBK是对GB2312的补充,增加了许多不常用汉字和繁体字。
其他文字的编码
不同文字有自己的编码。比如繁体中文( BIG5 ),日文(SHIFT_JIS)。
不同的编码可能使用相同的字节表示本国的字符。比如在GB2312编码中“我”字的编码是“CE D2”,而在BIG5编码中,“CE D2”对应的是“扂”字。
单字节编码和多字节编码
ACSII编码一个使用1个字节,是单字节编码,GB2312一个文字编码使用1个或2个字节,是多字节编码。
Unicode 统一码
为何需要Unicode
每种文字有各自的编码,但一个文本无法同时包含多种编码的文字。于是产生了 Unicode(统一码) ,为每种语言的文字设置了统一并且唯一的编码。有了Unicode,就可以跨语言、跨平台进行文字处理。
Unicode相关的概念
代码点
在Unicode字符集中的某个字符对应的代码值,称作 代码点(Code Point) ,用16进制书写,并加上U+前缀。比如,“田”的代码点是U+7530,”A”的代码点是U+0041。
代码平面
目前的Unicode字符分为17组编排,U+0000 至 U+10FFFF,每组称为 代码平面(Code Plane) ,每平面拥有65536(2的16次方)个代码点。
- U+0000 ~ U+FFFF划入 基本多语言平面 (Basic Multilingual Plane,简记为 BMP ),也叫做 平面0 。平面0包含了世界上多种文字。
- 其余划入16个 辅助平面(Supplementary Plane) ,代码点范围U+1 0000 ~ U+10 FFFF 。辅助平面中的文字通常使用不上。
平面0的部分编码区
- 0000-007F:C0控制符及基本拉丁文 (C0 Control and Basic Latin)
- 0080-00FF:C1控制符及拉丁文补充-1 (C1 Control and Latin 1 Supplement)
- 2000-206F:常用标点(General Punctuation)
- 3000-303F: CJK 符号和标点 (CJK Symbols and Punctuation) 中文标点
- 4E00-9FBF:CJK 统一表意符号(CJK Unified Ideographs) 包含汉字
- D800-DB7F:高位替代(High Surrogates)
- DB80-DBFF:高位专用替代(High Private Use Surrogates)
- DC00-DFFF:低位替代(Low Surrogates)
- E000-F8FF:自行使用区域 (Private Use Zone) 可以自行定义字符
- FFF0-FFFF:特殊 (Specials)
U+D800-U+DFFF,是代理区(Surrogate)。 UTF 16需要通过代理区表示平面0以外的一个字符。
Unicode与 UCS
UCS(Universal Character Set) 通用字符集 是与Unicode相似的一种统一编码,是由ISO国际标准化组织制定的,后来与Unicode统一了编码。如今,我们说Unicode,也就是UCS。
Unicode与UTF编码
UTF(Unicode Transfer Format) 统一码传输格式 定义了统一码的代码点如何转换到字节。
常见的Unicode传输格式
- UTF8,一个文字使用1~4个字节保存。英文数字使用1个字节,中文使用2个字节。优点是占用空间小,而且兼容ASCII,是使用广泛的编码,建议文件尽量使用这个格式。
- UTF16,一个文字使用2个字节(平面0的文字)或4个字节(其他平面的文字,使用代理对)保存,占用的存储空间适中,定长便于程序处理。UTF16不兼容ASCII。
- UTF32,一个文字使用固定4个字节保存,占用存储空间大,不常使用。UTF32不兼容ASCII。
通常我们说Unicode,指的是UTF16和UTF8编码,尤其指UTF16编码。
UCS-2与UCS-4
UCS-2和UCS-4是UCS定义的字符转换字节的方式。
UCS-2是UTF16的子集,不支持代理对,因此只能表示平面0的字符。
UCS-4和UTF32是大致等价的。
一般使用都是UTF来说明编码。
Unicode和BOM
UTF16和UTF32编码,根据字节的顺序,分为Big Endian(大字节序,高位在前)和Little Endian(小字节序,高位在后),为了区分字节顺序,需要在文本的开头加入BOM(Byte Order Mark) 字节序标志 。
UTF8没有字节序的区分,不需要BOM来表明字节序,但可以用BOM来表明编码方式。
不同编码的字节序标志
- UTF16 Big Endian: FF FE
- UTF16 Little Endian: FE FF
- UTF32 Big Endian:FF FE 00 00
- UTF32 Little Endian:00 00 FE FF
- UTF8:EF BB BF
Window记事本支持的编码
- ANSI 本机默认语言的编码,简体中文就是GB2312
- Unicode UTF16 LittleEndian
- Unicode BigEndian UTF16 BigEndian
- UTF-8 UTF8带BOM
记事本可以读取无BOM的UTF8编码,但写入UTF8编码时,总是带上BOM。
文本乱码
乱码的产生
乱码可以分成两种,一种是文本本身不是乱码,但是读取时选择了错误的编码,导致显示出来的是乱码,这种情况重新选择正确的编码读取就恢复正常了;另一种是文本本身经过不当处理,已经是乱码了,这种情况,乱码已经被保存,正确的文字已经丢失,无法恢复。
编码显示乱码
- 不同的环境默认编码不同导致。简体中文系统的默认编码是GB2312,将GB2312编码的文件发送给系统默认编码为SHIFT_JIS的用户,打开后的文件就是乱码。可以使用支持手动选择编码的软件选择正确的编码。
- 软件自身识别问题。以记事本为例,可以测试新建一个文本文档,输入”联通”二字保存后再打开,会是乱码,这是记事本错误的将GB2312编码推测成了UTF8。
编码保存乱码
- 包含多国语的文本,保存时选择了本地编码,可能会导致其他语言的文本无法保存,丢失的部分成了乱码。乱码部分无法恢复成正确的文本。
防止乱码产生
始终使用Unicode保存文本。UTF8,UTF16都是比较常用的编码。
经典乱码
- “烫烫烫”。在调试模式下,C语言会将栈的内存空间都填充为”CC”,而”CC CC”恰好是GB2312编码中的汉字”烫”,因此调试时经常可以看到“烫烫烫”。
- “锟斤拷”。编码转换时读取原文本时使用了错误的编码,转换后又以错误的编码读取。在将一种编码转换到UTF8编码时,由于使用错误的编码读取文本,比如文本本来已经是UTF8编码了,却将其当做GB2312编码,然后转换成UTF8了编码。转换过程中有无法转换成Unicode的文字,Unicode使用”�(U+FFFD)”进行替代,U+FFFD通过UTF8编码后的字节是”EF BF BD”,转换后的文本(乱码)又以GB2312的编码进行读取。无法转换的文字重复后,字节就是”EF BF BD EF BF BD”,这便恰好是是锟(EF BF)斤(BD EF)拷(DF BD)的GB2312编码。
相关文章
本站已关闭游客评论,请登录或者注册后再评论吧~