字符编码种类有多少种?
摘要:BOM头 BOM头全程Byte Order Mark (字节顺序标记), 是Unicode编码标准中,最早是用于UTF3216中标识字节顺序的特殊字符,后来随着UTF-8的出现,为了兼容,又有了标识文本编码格式的作用。 最初主要是为了解决
BOM头
BOM头全程Byte Order Mark (字节顺序标记), 是Unicode编码标准中,最早是用于UTF32/16中标识字节顺序的特殊字符,后来随着UTF-8的出现,为了兼容,又有了标识文本编码格式的作用。
最初主要是为了解决UTF32/16编码方案中大小端的问题,(大端BE:高字节在前,小端LE:低字节在前)。所以需要在字符串前增加一个特殊标记,以方便识别解析。
随着UTF-8的出现,不再需要BOM头。但微软为了方便自家软件能快速区分UTF-8与ANSI编码,而额外引入了非标准拓展。因此有了独特的UTF-8 BOM 编码方式
不同Unicode编码中的BOM头表现
编码格式
BOM头字节序列
长度
说明
UTF-8 BOM (微软特色)
EF BB BF
3字节
仅作编码标识,无字节顺序问题
UTF-8
-
-
-
UTF-16 BE(大端)
FE FF
2字节
表示高位字节在前
UTF-16 LE(小端)
FF FE
2字节
表示低位字节在前
UTF-32 BE
00 00 FE FF
4字节
表示高位字节在前
UTF-32 LE
FF FE 00 00
4字节
表示低位字节在前
眼见为实
使用文本编辑器,选择另存为,保存为不同的编码方案
public static void Run()
{
var utf8_path = @"C:\Users\liu\Documents\utf-8.txt";
var utf8_bom_path = @"C:\Users\liu\Documents\utf-8 bom.txt";
var utf16_le_path = @"C:\Users\liu\Documents\utf-16 be.txt";
var utf16_be_path = @"C:\Users\liu\Documents\utf-16 le.txt";
var utf8= BitConverter.ToString(File.ReadAllBytes(utf8_path));
Console.WriteLine("utf8 无bom: "+utf8 +"\n");
var utf8_bom= BitConverter.ToString(File.ReadAllBytes(utf8_bom_path));
Console.WriteLine("utf8 有bom: "+utf8_bom + "\n");
var utf16_le= BitConverter.ToString(File.ReadAllBytes(utf16_le_path));
Console.WriteLine("utf-16 be大端: "+utf16_le + "\n");
var utf16_be = BitConverter.ToString(File.ReadAllBytes(utf16_be_path));
Console.WriteLine("utf-16 le小端: "+utf16_be + "\n");
}
为什么UTF-8不需要BOM
BOM的本质是为了解决UTF-16/32大小端歧义的问题,而UTF8的编码特性从根本上解决了BOM要处理问题,所以BOM对UTF-8而言既无必要,而且还属于"额外附加"的内容。
UTF-16/32为什么需要
假如我要传输一个字符串“中“,Unicode编码:U+4E2D,在我传输给你的过程中,它可以是FE-FF-4E-2D(大端),也可以是FF-FE-2D-4E(小端),如果我没有标识字节顺序,你如何解析?
UTF-8 核心编码规则
要想知道为什么UTF-8不需要BOM,先从它的原理开始说起。
可变长编码
用1-4个字节表示一个Unicode字符,码点越小,占用的字节数越小。
标准的字节格式
每个字符的起始字节,会有一个特殊标识来表示该字符占用的总字节数,后续的字节用固定格式来表示,相当于有一个标准模板来定义UTF-8字符。
