织梦cms网站更新,怎么制作ppt用什么软件,wordpress 博客二号,wordpress静态链接设置完了4041. 
当用一个软件(比如Windows记事本或Notepad)打开一个文本文件时#xff0c;它要做的第一件事是确定这个文本文件究竟是使用哪种编码方式保存的#xff0c;以便于该软件对其正确解码#xff0c;否则将显示为乱码。 
一般软件确定文本文件编码方式的方法有如下三种#xf…1. 
当用一个软件(比如Windows记事本或Notepad)打开一个文本文件时它要做的第一件事是确定这个文本文件究竟是使用哪种编码方式保存的以便于该软件对其正确解码否则将显示为乱码。 
一般软件确定文本文件编码方式的方法有如下三种 
检测文件头标识提示用户手动选择根据一定的规则自行推断。
2. 
文件头标识一般指的是字节顺序标记BOM(Byte Order Mark)位于文件的最开始。当打开一个文本文件时就BOM而言有如下几种情形 
BOM为EF BB BF ——表示编码方式为UTF-8BOM为FF FE ——表示编码方式为UTF-16LE(小端序)BOM为FE FF ——表示编码方式为UTF-16BE(大端序)BOM为FF FE 00 00 ——表示编码方式为UTF-32LE(小端序)BOM为00 00 FE FF ——表示编码方式为UTF-32BE(大端序)没有BOM ——要么显式地提示用户手动选择一种编码方式要么隐式地由软件按规则自行推断出编码方式。
3. 
接下来是见证诡异怪事的时刻。 
当你在简体中文版的Windows记事本里新建一个文件输入“联通”两个汉字之后保存为一个txt文件。然后关闭再次打开该txt文件后你会发现刚才输入并保存的“联通”两个汉字竟然莫名其妙地消失了取而代之的是几个乱码。如下图所示。 这是为什么呢难道是微软跟联通有仇吗 
原来当你用Windows记事本新建一个文本文件时其编码方式默认为ANSI编码(在简体中文版Windows中实际为GBK编码)没有BOM。 
(注Windows系统中的ANSI编码指的是在区域设置中所设置的系统默认编码方式在简体中文版Windows系统中指的是GBK即CP936代码页具体可参看前文《刨根究底字符编码之七——ANSI编码与代码页》 笨笨阿林原创文章转载请注明出处 
在这种编码方式下该文本文件仅仅保存了“联通”两个汉字的GB内码的四个字节如下所示(左边为十六进制右边为二进制)。 c1  1100 0001   aa  1010 1010   cd  1100 1101   a8  1010 1000 
通过Notepad的HEX-Editor插件可查看内码(十六进制)如下图所示。 通过UltraEdit的“十六进制编辑”模式也可查看内码(十六进制)如下图所示。 4. 
当用记事本再次打开该文本文件时由于没有BOM记事本又没有提供显式地提示用户手动选择编码方式的功能于是就只能隐式地按其推断规则自行推断推断的结果就是被误认为了这是一个UTF-8编码方式的文件。 
为什么会推断错误呢又为什么会将其编码方式错误地推断为UTF-8呢 
注意“联通”两个汉字的GB内码其第一第二个字节的起始部分分别是“110”和“10”第三第四个字节的起始部分也分别是“110”和“10”这刚好符合了UTF-8编码方式里的两码元序列的编码算法规则(即与UTF-8的两码元序列“110xxxxx 10xxxxxx”中的前缀码“110”和“10”刚好是完全一致的详见本系列文章中《刨根究底字符编码之十二——UTF-8究竟是怎么编码的》一文的介绍)。 
让我们按照UTF-8的编码算法规则将第一个字节的前缀码110去掉得到“00001”将第二个字节的前缀码10去掉得到“101010”将两者组合在一起得到“00001101010”再去掉多余的前导的0就得到了“0110 1010(十六进制为6A)这正好是Unicode字符集里的U006A也就是小写字母“j”的码点值。 
同理之后的第三个字节与第四个字节按同样的方法用UTF-8解码之后正好是Unicode字符集里的U0368这个字符为“ͨ”(抱歉这里的左双引号貌似被这个字符所影响看起来像是半角左双引号而无法正常显示为全角左双引号)很像是上标的一个小c这应该是个组合字符(组合字符是Unicode字符集中的一种特殊字符必须与其他字符组合在一起以形成一个新字符一般不单独使用可参看本系列文章前面相关文章中的介绍)。 
这就是只有“联通”两个汉字的文本文件没有办法在记事本里被正确解码显示的原因。这里要特别说明的是在记事本里打开时显示的不是“j”和“ͨ”而是显示为了“ͨ”(注意右上角是“ͨ”)。 
而用UltraEdit打开如果在设置中选择了“自动检测UTF-8文件”显示的是“j”和“ͨ”组合在一起的字符“jͨ”。注意这个字符不是小写字母“j”而是小写字母“j”上面的点变成了一个上标的小c因为U0368这个字符“ͨ”应该是个组合字符与其前面的小写字母“j”组合在一起而形成了一个新字符——jͨ再次提醒注意小写字母“j”上面的点变成了“c”。 注意在UltraEdit的早期版本中没有“自动检测UTF-8文件”这一选项 
5. 
这里还有一个问题既然已经推断为了UTF-8那为什么Windows记事本还是将前两个字节亦即原本为“联”字的GB内码的那两个字节显示为了“”这样的乱码而不是显示为小写字母“j”呢 
我想主要是因为小写字母“j”属于ASCII字符在UTF-8编码中ASCII字符属于单字节编码出现在双字节编码中是非正常的因而被Windows记事本认为是错误编码而UltraEdit则作了容错处理仍然将其解读为了小写字母“j”。 
而后两个字节亦即原本为“通”字的GB内码的那两个字节之所以Windows记事本将其按UTF-8编码的规则解读为了字符“ͨ”那是因为字符“ͨ”的UTF-8编码正好就是双字节编码因此按UTF-8编码的规则去解读的话不属于错误。 
笨笨阿林原创文章转载请注明出处 
6. 
其实用记事本默认的编码方式(ANSI)分别单独保存“联”字和“通”字为两个独立的txt文件则 
1) 再用记事本打开时“联”字显示的是“”“通”字显示的是“ͨ” 
2) 用UltraEdit打开时 (1) 如果选择了“自动检测UTF-8文件”“联”字显示的是小写字母“j”“通”字显示的“ͨ”(不过看不清我开始还以为是个空格) (2) 如果没有选择“自动检测UTF-8文件”“联”字和“通”字均能正常显示(说明这种情况下UltraEdit正确地推断出了编码方式为GBK从这一点来看UltraEdit比Windows记事本要强) 
3) 用NotePad打开时 (1) 如果在“格式”中选择的是“以ANSI格式编码”(亦即显式地手动选择了正确的编码方式)“联”字和“通”字均能正常显示 (2) 如果编码方式选择的是UTF-8、UTF-8无BOM、UCS-2 Big Endian或UCS-2 Little Endian时则“联”字均显示为“xC1xAA”(有意思的是直接复制“xC1xAA”然后粘贴到Word里则显示为了小写字母“j”)“通”字均显示为“ͨ”。 
而如果是用记事本默认的编码方式(ANSI)保存“联通通信”四个字则用记事本、UltraEdit(即便选择的是“自动检测UTF-8文件”的情况下)打开后都可正常显示。 
这充分说明Windows记事本在文件头没有BOM的情况下只能自行推断由于“联通”两个汉字保存为ANSI编码方式时内码只有四个字节在信息不够充足的情况下(尤其是其内码又刚好符合了UTF-8的编码算法规则)于是被错误地推断为了UTF-8编码方式当以ANSI编码方式保存的是“联通通信”四个汉字时内码有八个字节这时信息较为充足因此被正确地推断为了ANSI编码方式(在简体中文版Windows中ANSI编码默认为GBK编码)。 
7. 
上面分析的是Windows系统中采用ANSI编码时没有添加BOM的情况。那么对于采用非ANSI编码时添加了BOM的情况是否就万事大吉了呢其实添加BOM来标记字符编码表面看起来貌似不错但实际上经常会带来麻烦因为它和很多协议、规范并不兼容。 
Windows里的软件在采用非ANSI编码时即便对于根本不存在字节序问题的UTF-8编码默认也会添加BOM(详见之前文章《刨根究底字符编码之十一——UTF-8编码方式与字节序标记》的介绍)而像Unix、Linux、Mac OS等*nix系统对于UTF-8编码都默认不添加BOM。 
既然*nix系统都可以不添加BOM那为什么Windows系统却非要添加BOM呢这很可能是因为Windows系统有大量普通用户使用在必须兼容传统ANSI编码的情况下从用户体验角度考虑而没有采用显式地要求用户手动选择字符编码方式的做法因此特别依赖于通过BOM来防止隐式地自行推断字符编码方式而出错。 
微软这种为了照顾广大普通用户而从用户体验角度出发“好心办坏事”的例子其实还有很多。 
8. 
因此在Windows系统中尽量不要使用记事本来打开并编辑文本文件尤其是作为程序员应使用Notepad或UltraEdit等更为专业的文本文件编辑软件。 
这一方面是可以避免出现上述这样的“诡异”错误另一方面也是为了避免Windows记事本“多此一举”地添加BOM(详见下面附文中的解释)从而给在与其他系统(比如*nix系统)交流时带来不必要的麻烦。 附Windows记事本中对常用编码方式自行其是的“奇葩”命名 Windows记事本中对常用编码方式的命名非常“奇葩”微软这种自行其是的非标准命名很是令人费解现解释如下。 1 ANSI指的是对应当前系统区域设置(即系统locale)中的默认ANSI编码不带BOM。在简体中文版Windows系统中默认ANSI编码指的就是GBK编码即CP936具体可参看前文《刨根究底字符编码之七——ANSI编码与代码页》。 2 Unicode指的是带有BOM的小端序UTF-16(即UTF-16LE with BOM)。 3 Unicode big endian指的是带有BOM的大端序UTF-16(即UTF-16BE with BOM)。 4 UTF-8指的是带有BOM的UTF-8(即UTF-8 with BOM)。UTF-8编码方式实际上并不存在字节序的问题之所以仍然“多此一举”地添加BOM应该是由于要兼容不添加BOM的ANSI编码从用户体验角度考虑避免用户显式地手动选择编码方式。 (注如果UTF-8编码不添加BOM则有两种不添加BOM的编码方式从而导致隐式地自行推断编码方式更容易出错上文所介绍的对“联通”推断出错即是明证。当然反过来也说明了Windows记事本对于不添加BOM的UTF-8编码其实同样是支持的而并非简单粗暴地直接提示错误这应该是为了兼容*nix系统不添加BOM的做法而不得不采取的策略。只是这样一来就很难避免陷入左右为难的困境。) 
笨笨阿林原创文章转载请注明出处 未完待续