微软平台文件编码兼容Unix不生成BOM头

2021-03-22 15:25:15 浏览数 (1)

遇到一个问题,.NET后台生成HTML到了Linux上就会多出一行乱码,样式会乱,查原因是因为.NET运行在windows平台,生成UTF-8会自动加一个BOM头。

去掉BOM其实关键代码就这么一行

System.Text.UTF8Encoding utf8 = new System.Text.UTF8Encoding(false);                 StreamWriter sw = new StreamWriter(nFile,utf8);

下面2个文件是去掉的和未去掉的,其中EF BB BF就是BOM头。

代码语言:javascript复制
private bool FileStreamWriteFile(Model.RecommendHtml model)
        {
            try
            {
                string writeUrl = ConfigurationManager.AppSettings["unix21"];
                string htmlurl = writeUrl   @"html"   model.ID   ".html";
                FileStream nFile = new FileStream(htmlurl, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                nFile.Seek(0, SeekOrigin.Begin);
                nFile.SetLength(0); 
                System.Text.UTF8Encoding utf8 = new System.Text.UTF8Encoding(false);
                StreamWriter sw = new StreamWriter(nFile,utf8);
                sw.Write(model.RecommendContent);
                sw.Close();
                nFile.Close();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

关于UTF-8和BOM头的参考信息:

UTF-8 不需要 BOM,尽管 Unicode 标准允许在 UTF-8 中使用 BOM。 所以不含 BOM 的 UTF-8 才是标准形式,在 UTF-8 文件中放置 BOM 主要是微软的习惯(顺便提一下:把带有 BOM 的小端序 UTF-16 称作「Unicode」而又不详细说明,这也是微软的习惯)。 BOM(byte order mark)是为 UTF-16 和 UTF-32 准备的,用于标记字节序(byte order)。微软在 UTF-8 中使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码明确区分开,但这样的文件在 Windows 之外的操作系统里会带来问题。

其实说BOM是个坏习惯也不尽然。BOM也是Unicode标准的一部分,有它特定的适用范围。通常BOM是用来标示Unicode纯文本字节流的,用来提供一种方便的方法让文本处理程序识别读入的.txt文件是哪个Unicode编码(UTF-8,UTF-16BE,UTF-16LE)。Windows相对对BOM处理比较好,是因为Windows把Unicode识别代码集成进了API里,主要是CreateFile()。打开文本文件时它会自动识别并剔除BOM。Windows用这个有历史原因,因为它最初脱胎于多代码页的环境(ANSI环境)。而引入Unicode时Windows的设计者又希望能在用户不注意的情况下同时兼容Unicode和非Unicode(Multiple byte)文本文件,就只能借助这种小trick了。相比之下,Linux这样的系统在多locale的环境中浸染的时间比较短,再加上社区本身也有足够的动力轻装前进(吐槽:微软对兼容性的要求确实是到了非常偏执的地步,任何一点破坏兼容性的做法都不允许,以至于很多时候是自己绑住自己的双手),所以干脆一步到位进入UTF-8。当然中间其实有一段过渡期,比如从最初全UTF-8的GTK 2.0发布到基本上所有GTK开发者都弃用多locale的GTK 1.2,我印象中至少经历了三到四年。

BOM不受欢迎主要是在UNIX环境下,因为很多UNIX程序不鸟BOM。主要问题出在UNIX那个所有脚本语言通行的首行#!标示,这东西依赖于shell解析,而很多shell出于兼容的考虑不检测BOM,所以加进BOM时shell会把它解释为某个普通字符输入导致破坏#!标示,这就麻烦了。其实很多现代脚本语言,比如Python,其解释器本身都是能处理BOM的,但是shell卡在这里,没办法,只能躺着也中枪。说起来这也不能怪shell,因为BOM本身违反了一个UNIX设计的常见原则,就是文档中存在的数据必须可见。BOM不能作为可见字符被文本编辑器编辑,就这一条很多UNIX开发者就不满意。

http://www.cnblogs.com/findumars/p/3620078.html

=============================================

Q: What is a BOM?

A: UTF-8 编码的文件可以分为no BOM 和 BOM两种格式。

何谓BOM? "EF BB BF" 这三个字节就叫BOM,BOM的全称叫做"Byte Order Mard".在utf-8文件中常用BOM来表明这个文件是UTF-8文件,而BOM的本意实在utf16中用来表示高低字节序列的。

在字节流之前有BOM表示采用低字节序列(低字节在前面),而utf8不用考虑字节序列,所以其实有无BOM都可以。

用以下方法就可以去掉BOM签名

Code

System.Text.UTF8Encoding utf8 = new System.Text.UTF8Encoding(false); StreamWriter stream = new StreamWriter(Server.MapPath("normren.html"), false,utf8); stream.Write("Content"); stream.Close();

//以前看到有人好像要改写utf8让他不生成标记,大可不用那样,系统已经提供的相关功能了。               StreamWriter dout = new StreamWriter("1.html", false, new UTF8Encoding(false));               dout.Write("sdsdsd");               dout.Close(); 

参考:http://blog.163.com/yanfeng_0/blog/static/6200414520096303911545/

==================================================

BOM(Byte Order Mark),是UTF编码方案里用于标识编码的标准标记,在UTF-16里本来是FF FE,变成UTF-8就成了EF BB BF。这个标记是可选的,因为UTF8字节没有顺序,所以它可以被用来检测一个字节流是否是UTF-8编码的。微软做这种检测,但有些软件不做这种检测,而把它当作正常字符处理。

微软在自己的UTF-8格式的文本文件之前加上了EF BB BF三个字节, windows上面的notepad等程序就是根据这三个字节来确定一个文本文件是ASCII的还是UTF-8的, 然而这个只是微软暗自作的标记, 其它平台上并没有对UTF-8文本文件做个这样的标记。

也就是说一个UTF-8文件可能有BOM,也可能没有BOM,那么怎么区分呢?三种方法。1,用UltraEdit-32打开文件,切换到十六进制编辑模式,察看文件头部是否有EF BB BF。2,用Dreamweaver打开,察看页面属性,看“包括Unicode签名BOM”前面是否有个勾。3,用Windows的记事本打开,选择 “另存为”,看文件的默认编码是UTF-8还是ANSI,如果是ANSI则不带BOM。

参考:http://blog.163.com/result_2205/blog/static/13981945020102954023564/

本文由来源 21aspnet,由 javajgs_com 整理编辑,其版权均为 21aspnet 所有,文章内容系作者个人观点,不代表 Java架构师必看 对观点赞同或支持。如需转载,请注明文章来源。

0 人点赞