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

遇到一个问题,.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头。

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/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 18:35:48

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

一键生成JNI头文件方法二

经常使用java的同学一定都接触过JNI(Java Native Interface)吧.JNI为我们提供了java<---->C/C++之间的接口,使得我们可以在java中调用C程序,以便实现一些计算复杂度较高的程序(如图像处理.信号处理等).另外,也方便我们使用很多优秀的C库. 使用javah生成本地方法头文件 JNI怎么使用在这里我就不介绍了.今天主要来说一下JNI的本地方法头文件如何生成,以及怎么方便地在eclipse中一键生成.当你使用JNI时,需要在你的java程序中声明一个类,并

什么是文件的BOM头

1.什么是BOM? BOM是用来判断文本文件是哪一种Unicode编码的标记,其本身是一个Unicode字符("\uFEFF"),位于文本文件头部. 在不同的Unicode编码中,对应的bom的二进制字节如下: Bytes Encoding FE FF UTF16BEFF FE UTF16LEEF BB BF UTF8 所以我们可以根据文件头部的几个字节和上面的表格对应来判断该文件是哪种编码形式. 2. 如何查看你文件的BOM字符? BOM头在记事本中是看不到的 以UTF8为例,新建一

关于如何在Android、Java等非微软平台上建立高信任的SharePoint应用程序

关于如何在非微软平台上建立高信任的SharePoint应用程序 原文 :http://blogs.msdn.com/b/kaevans/archive/2014/07/14/high-trust-sharepoint-apps-on-non-microsoft-platforms.aspx 1.前言 开篇明之,哥无代码发布,也不提供解决方案. 我只是说明在非微软技术平台上建立低信任或是高信任应用程序是非常自由的(PS:也是非常痛苦的). 作为一个微软技术的研发者,我也长时间没有写Java或是PH

Android SO文件的兼容和适配

开发Android应用时,有时候Java层的编码不能满足实现需求,就需要到C/C++实现后生成SO文件,再用System.loadLibrary()加载进行调用,这里成为JNI层的实现.常见的场景如:加解密算法,音视频编解码等.在生成SO文件时,需要考虑适配市面上不同手机CPU架构,而生成支持不同平台的SO文件进行兼容.目前Android共支持七种不同类型的CPU架构,分别是:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIP

理清文件编码,告别中文乱码

理清文件编码,告别中文乱码 在工作中少不了碰到文件乱码的问题,面对这么多的中文汉字编码,真不知该选哪个好,不如彻底搞清楚,让乱码灰飞烟灭:以下介绍文本编码中常用到的几种:iso8859-1.GDK/GB2312.ANSI.unicode 以及UTF : iso8859-1 iso8859-1 通常叫做Latin-1,属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列.比如,字母a的编码为0x61=97. 很明显,iso8859-1编码表示的字符范围很窄,无法表示中文字符.但是,由于

修改VISUAL STUDIO EXPRESS 2012新建C++文件编码

本站文章除注明转载外,均为本站原创或者翻译. 本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商: 本站部分原创和翻译文章提供markdown格式源码,欢迎使用文章源码进行转载: 本文标题:修改Visual Studio Express 2012新建C++文件编码 本文链接:http://zengrong.net/post/1900.htm 2013-12-03 更新:增加关于UTF-8(BOM)的说明 我突然发现Visual Studio Expres

文件编码和文件内的字符串字面值编码是两个概念

我们知道,CALabel的字符串使用的是UTF8编码,通常在xcode下,直接CALabel *p = ...; p->setText("汉字"),显示汉字是没有任何问题的,但是,在VS2013中却显示的是乱码.很多人在群里面问了,我都答:请使用UTF8编码.他说,我的文件是UTF8格式的啊.呵呵,没那么简单好吗,文件编码和字符串字面值编码是两个概念. VS2013的一条预编译指令#pragma execution_character_set("utf-8")

解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)——ubuntu环境设置默认是utf-8,文件编码可使用Encodersoft批量转换

一.Qt环境设置 文件从window上传到Ubuntu后会显示乱码,原因是因为ubuntu环境设置默认是utf-8,Windows默认都是GBK.Windows环境下,Qt Creator,菜单->工具->选项->文本编辑器->行为->文件编码:默认编码:System(简体中文windows系统默认指的是GBK编码,即下拉框选项里的GBK/windows-936-2000/CP936/MS936/windows-936) 二.编码知识科普Qt常见的两种编码是:UTF-8和GB

C# IO操作(四)大文件拷贝(文件流的使用)、文件编码

     大文件拷贝(文件流的使用).文件编码 首先说一下大文件拷贝和文件流,因为计算机的内存资源是有限的,面对几个G甚至更大的文件,需要通过程序来完成拷贝,就需要用到文件流(因为我们无法做到把文件一次性加载到内存中:事实上,内存也不允许这么干),所以在C#中出现了内存流这个东西.先看下面的内容,File类中的常用读取文件方法会将文件内容一次性全部加载到内存中: 1 string sPath = @"C:\Users\Chens-PC\Desktop\Nginx.txt"; 2 //F