http://www.cnblogs.com/swtseaman/archive/2011/05/17/2048689.html
文件的字符集在Windows下有两种,一种是ANSI,一种Unicode。
对于Unicode,Windows支持了它的三种编码方式,一种是小尾编码(Unicode),一种是大尾编码(BigEndianUnicode),一种是UTF-8编码。
我们可以从文件的头部来区分一个文件是属于哪种编码。当头部开始的两个字节为 FF FE时,是Unicode的小尾编码;当头部的两个字节为FE FF时,是Unicode的大尾编码;当头部两个字节为EF BB时,是Unicode的UTF-8编码;当它不为这些时,则是ANSI编码。
按照如上所说,我们可以通过读取文件头的两个字节来判断文件的编码格式,代码如下(C#代码):
程序中System.Text.Encoding.Default是指操作系统的当前 ANSI 代码页的编码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public
System.Text.Encoding GetFileEncodeType(
string
filename)
{
System.IO.FileStream fs =
new
System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
System.IO.BinaryReader br =
new
System.IO.BinaryReader(fs);
Byte[] buffer = br.ReadBytes(2);
if
(buffer[0]>=0xEF)
{
if
(buffer[0]==0xEF && buffer[1]==0xBB)
{
return
System.Text.Encoding.UTF8;
}
else
if
(buffer[0]==0xFE && buffer[1]==0xFF)
{
return
System.Text.Encoding.BigEndianUnicode;
}
else
if
(buffer[0]==0xFF && buffer[1]==0xFE)
{
return
System.Text.Encoding.Unicode;
}
else
{
return
System.Text.Encoding.Default;
}
}
else
{
return
System.Text.Encoding.Default;
}
}
|
windows下的notepad另存为选项有关于编码的选择,ANSI、Unicode、Unicode big endian、UTF-8四种选择编码方式。其中ANSI是与你使用的windows操作系统的语言有关系的,向windows 7 简体中文版就是GBK(用一个字节表示英文,用两个字节表示一个中文)。第二个选项Unicode其实是指Unicode16
但是了,UTF-8也可以不要这三个字节的BOM,像用php的GD库生成图片时,如果有了BOM就会出错。而且在windows平台上,用notepad打开一个没有BOM的文本文件,也能正常显示,而不会当做ANSI(GBK)来处理。但是有这样的一个趣事,就是在notepad中输入“联通”两个中文,保存到本地,再打开,会发现乱码。这是为什么呢?
这个就设计到notepad判断文本编码的原理了。(这个原理是根据实验结果推测的,本人不保证其绝对与微软的思路一致)
notepad打开一个文本,有BOM这很容易判断是UTF系列编码,因为UTF-8,UTF-16 big endian, UTF-16 little endian ,UTF-32 big endian, UTF-32 little endian 的BOM都不一样。但是如果文本没有BOM,又不能立刻判定其为ANSI(GBK)编码,因为也有可能是无BOM的UTF-8。所以notepad会根据UTF-8的编码原理推测编码
UCS-4编码
U+00000000 – U+0000007F
U+00000080 – U+000007FF
U+00000800 – U+0000FFFF
U+00010000 – U+001FFFFF
……
比如中文都是用三个字节表示,若无BOM,则从文本第一个字节开始,按照UTF-8的编码规则去验证字符编码,例如:
第一个字节的第一个bit为0,说明是个ANSII字符,继续查看第二个比特,若第一个比特是1,则查看第二个比特,若第二个比特为0,说明这不是一个UTF-8编码的文本。依次类推,若一旦有一个bit不满足UTF-8编码要求,就判定文本为ANSI(GBK),若知道文本结束都不能判定,则说明文本是UTF-8编码的。
所以现在我们就能明白为什么在notepad中“联通”会乱码了。notepad中文本默认按ANSI(GBK)保存,没有BOM,打开时notepad会判断其编码,巧合的是联通的ANSI(GBK)编码为 C1 AA CD A8
11000001
知道了原理,我们就可以编写判断文本编码的软件了。这里我就不贴代码了。