Windows文本文件编码(ANSI和Unicode)

Windows文本文件编码(ANSI和Unicode)

Jan 13, 2014
Coding
字符编码

Unicode 和 字节序 #

Unicode 有 UCS-2 和 UCS-4 两种,分别使用2个字节、4个字节编码一个字符。通常说的Unicode都是指 UCS-2。由于一个字符有多个字节,所以Unicode在传输和存储时就存在高位字节和低位字节的顺序问题,即字节序问题,由此分为小端模式(little endian)和大端模式(big endian)。

  • 小端模式:低字节在前,高字节在后。如”汉“ 存储为 49 6C (“汉"字的 Unicode 编码是 6C49,UTF-16存储格式)
  • 大端模式:高字节在前,低字节在后。如“汉” 存储为 6C 49

“汉"字的Unicode编码是6C49,但在传输(包括存储,下同)时不一定就是直接传6C49,而是有一套转换规则将Unicode编码转换成相应的传输格式。Unicode的传输格式称为UTF(Unicode Transfer Format),分为 UTF-8 和 UTF-16。

  • UTF-8:将Unicode编码每8位为一个单元,进行传输。
  • UTF-16:将Unicode编码每16位为一个单元,对于UCS-2编码,基本的UCS-2编码和UTF-16是直接对应的(因为都为16位),大端模式的UTF-16就是对应的UCS-2编码(如上面的’汉’字存储示例)

更多关于字符编码内容,参考 字符编解码的故事(ASCII,ANSI,Unicode,Utf-8区别)

BOM #

Unicode中使用BOM来标记字节序。Byte Order Mark,字节序标识。

在Unicode 编码中有一个叫做 “ZERO WIDTH NO-BREAK SPACE” 的字符,它的编码是FEFF。而 FEFF 在Unicode中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE”。这样如果接收者收到FE FF,就表明这个字节流是Big-Endian的;如果收到FF FE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。引自 http://www.fmddlmyy.cn/text6.html

FF FE 为小端,FE FF为大端

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。 Windows就是使用BOM来标记文本文件的编码方式的。

Windows文本文件编码 #

Windows记事本保存的编码类型有ANSI、Unicode、Unicode big endian以及UTF-8。

  • ANSI :当前Windows系统的编码(简体中文为GBK)[注1]
  • Unicode,带BOM 的Little Endian UTF-16
  • Unicode big endian,带BOM的Big Endian UTF-16。
  • UTF-8,带BOM的UTF-8 [注2]。

[1] ANSI 指 ANSI code pages,ANSI code pages 这个名字是微软的历史遗留问题,正式名称是 Windows code pages。它实际上是一系列的编码集合,根据操作系统区域设置而激活其中一种作为默认ANSI编码。所以实际上是以当前系统的编码为准的,英文系统上的code page可能是1252,简体中文系统用的code page 是 936(GBK 字符集)

[2] 微软在自己的UTF-8格式的文本文件之前加上了EF BB BF三个字节(即UCS-2 中的FF FE的UTF-8编码),windows上面的记事本等程序就是根据这三个字节来确定一个文本文件是ASCII的还是UTF-8的,然而这个只是微软暗自作的标记,其它平台上并没有对UTF-8文本文件做个这样的标记。[引自 互动百科:BOM]

使用Windows记事本新建一个空白文本文件,输入 中文abc 几个字符,然后分别另存为上述四种不同的编码格式。

Windows text file encoding

ANSI 对应 ascii.txt 文件 #

ascii.txt文件大小为7B。因为GBK编码中字母占1B,汉字占2B,所以三个字母3B,两个汉字4B。使用 UltroEdit 以十六进制格式打开该文件,内容为

D6 D0 CE C6 61 62 63

D6D0 CEC6分别为’中’ 和 ‘文’ 的GBK编码,61 62 63 是 ‘a’、 ‘b’ 、‘c’的编码(和ASCII码相同)

Unicode 对应 unicode.txt 文件 #

使用带BOM的Big Endian UTF-16存储。文件大小12B(BOM占2B,5个字符各占2B)。十六进制打开该文件,内容为

FF FE 2D 4E 87 65 61 00 62 00 63 00

其中FF FE为BOM,表示Little Endian 。后面每两个字节表示一个字符(无论是汉字还是字母)

4E 2D、65 87 分别是’中’、‘文’的UCS-2编码。小端模式,所以低位2D在前,高位4E在后。

Unicode big endian 对应 unicode-big-endian.txt 文件 #

使用带BOM的Big Endian UTF-16存储。十六进制打开该文件,内容为

FE FF  4E 2D 65 87  00 61  00 62  00 63

其中FE FF为BOM,表示Big Endian 。后面每两个字节表示一个字符,字节序与Little Endian的刚好相反。

UTF-8 对应 utf8.txt 文件 #

使用带BOM的UTF-8存储。十六进制打开该文件,内容为

EF BB BF E4 B8 AD E6 96 87 61 62 63

前三个字节EF BB BF 为BOM,表示这个文件是utf8格式存储的文件。