网上也有许多关于纯文本的讨论,如果在搜索“乱码”,更是不尽其数。如果你开始命令行,开始编码,开始数据分析,开始操作中文,存文本及其字符编码便是最基础的东西。而往往基础的东西,真正弄懂更为不易,而或者你已经有了多年相关的经验,也不一定搞清楚了。
存文本由可打印字符组成,人可以直接阅读和理解其形式。
纯文本并非意味着文本是无结构的,HTML、SGML、XML等都是有良好结构定义的存文本,与直接的二进制编码相比,纯文本所处的层面往往更高。大多数二进制格式的问题在于,理解数据所必须的语境与数据本身是分离的,没有应用逻辑对其进行解释,这些数据绝对没有意义,但是通过存文本,可以获得自描述的、不依赖创建它的应用的数据流。对于大多数二进制文件,要成功的进行解析,你必须了解整个格式的所有细节。
计算机的一切,到底都是二进制的,所以文本文件是一种特殊的二进制文件,特殊在于这些二进制都对应字符编码,可以容易的进行各种操作。
——2013年5月15日
最重要或者最难理解的就是其编码格式,计算机中最小的操作单位是字节(Byte),通常每8位(bit)组成一个字节,1KB=1024Byte=1024*8bit,二进制也就是由0和1组成的串,为了书写或者表示的方便,通常用16进制来表示二进制,如下表格:
0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
8 | 9 | A | B | C | D | E | F |
一个字节可以用两位的十六进制表示,00~FF,共256位0~255。下表是二进制的位数,可以表示的字符数目。
2^0 | 2^1 | 2^2 | 2^3 | 2^4 | 2^5 | 2^6 | 2^7 | 2^8 | 2^9 | 2^10 |
0 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 |
二进制如何表示字符,也就是编码格式标准制定的缘由。总的来讲,编码可以分为两类:
Unicode is a computing industry standard for the consistent encoding, representation and handling of text expressed in most of the world’s writing systems.
在表示一个Unicode的字符时,通常会用“U+”然后紧接着一组十六进制的数字来表示这一个字符。Unicode的实现方式不同于编码方式。一个字符的Unicode编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF)。
目前通用的实现方式是UTF-16小端序(LE)、UTF-16大端序(BE)和UTF-8。在Windows 附带的记事本(Notepad)中,“另存为”对话框可以选择的四种编码方式除去非Unicode编码的ANSI(对于英文系统即ASCII编码,中文系统则为GB2312或Big5编码) 外,其余三种为“Unicode”(对应UTF-16 LE)、“Unicode big endian”(对应UTF-16 BE)和“UTF-8”。
UTF-8是UNICODE的一种变长字符编码,由Ken Thompson于1992年创建。现在已经标准化为RFC 3629。UTF-8用1到6个字节编码UNICODE字符。
从Unicode到UTF-8的编码方式如下:
Unicode编码(16进制) | UTF-8 字节流(二进制) |
000000 – 00007F | 0xxxxxxx |
000080 – 0007FF | 110xxxxx 10xxxxxx |
000800 – 00FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
010000 – 10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0×00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。
例如:“汉”字的Unicode编码是0x6C49。0x6C49在0×0800-0xFFFF之间,使用用3字节 模板了:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
对于ANSI编码方式,存在不同的字符集(Charset), 要正确解析一个ANSI字符串,还要选择正确的字符集,每个字符集都有一个唯一的编号,称为代码页(Code Page)。简体中文(GB2312)的代码页为936,而系统默认字符集的代码页为0,它表示根据系统的语言设置来选择一个合适的字符集。
汉字编码中现在主要用到的有三类,包括GBK,GB2312和Big5。
R.C. GB Uni. UTF-8 R.C. GB Uni. UTF-8 1601 啊 B0A1 554A E5958A 1602 阿 B0A2 963F E998BF 1603 埃 B0A3 57C3 E59F83 1604 挨 B0A4 6328 E68CA8 1605 哎 B0A5 54CE E5938E 1606 唉 B0A6 5509 E59489 1607 哀 B0A7 54C0 E59380 1608 皑 B0A8 7691 E79A91 1609 癌 B0A9 764C E7998C 1610 蔼 B0AA 853C E894BC 1611 矮 B0AB 77EE E79FAE 1612 艾 B0AC 827E E889BE 1613 碍 B0AD 788D E7A28D 1614 爱 B0AE 7231 E788B1
ASCII
ASCII使用一个字节的其中7位二进制数来表示所有的大写和小写字母,数字0 到9、标点符号, 以及在美式英语中使用的特殊控制字符。
如前所述,每种编码都有一种规范,如果按照编码方式,能将其全部读为字符串,就是文本文件。由于编码方式的差异,程序是很容易通过判断,来知道其编码方式,如果都不行,那就是二进制了。
另外还有一种方式,BOM,Windows就是使用BOM来标记文本文件的编码方式的操作系统。什么是BOM, w3.org 标准 FAQ 中对此问题有一个专门的描述:http://www.w3.org/International/questions/qa-utf8-bom,具体如下:
在UCS 编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输 字符”ZERO WIDTH NO-BREAK SPACE”。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little- Endian的。因此字符”ZERO WIDTH NO-BREAK SPACE”又被称作BOM。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE”的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
各种系统、工具,对于BOM处理也不一样:
联系客服