UTF-8 的BOM带来的麻烦

工作需要我用程序生成一个html文件。

由于服务器端使用apache+Tomcat来执行html和jsp文件。

开始生成html文件放在apache目录下,页面无法默认正常识别我页面设置的编码。



必须手动在浏览器上选择Encoding->简体中文(GB2312)才可以正常显示。

这样当然是不行了。

由于我们原来有一个页面是可以正常显示中文的,查看了一下,是UTF-8的格式,于是我也修改程序。

a.修改了页面的编码声明:



b.修改了写字节流的一个方法:

public void htmlWrite(String charsetName) {

        try {

            out = new BufferedWriter(new OutputStreamWriter(

                        new FileOutputStream(outFileName), "UTF-8"));

            out.write(res);

            out.flush();

if (out != null) {

                out.close();

            }

        } catch (Exception e) {

            try {

                if (out != null) {

                    out.close();

                }

            } catch (IOException e1) {

                System.out.print("write errors!" + e);

            }

System.out.print("write errors!" + e);

        }

    }

这样,我又生成了一个html,放在服务器下面,可问题又来了,还是无法正常显示,即浏览器无法默认识别为UTF-8的编码方式。奇怪,使用EmEditor打开,和好用的那个页面对比。没有任何问题。唯一的区别在于:

    我生成的那个html文件被EmEditor认为UTF-8 with Signature。而好用的那个html文件被EmEditor认为UTF-8 without Signature.

    对于这两种UTF-8格式的转换,我查看了网上信息,点击记事本,EmEditor等文本编辑器的另存为,当选择了UTF-8的编码格式时,Add a Unicode Signature(BOM)这个选项被激活,只要选择上,我的文件就可以存为UTF-8 with Signature的格式。可是,问题就在于,我用java怎么让我的文件直接生成为 UTF-8 with Signature的格式。

    开始上google搜索UTF-8 with Signature,BOM,Add a Unicode Signature等关键字。

http://www.unicode.org/unicode/faq/utf_bom.html#BOM

我大致了解了他们两个的区别。

Q: What is a BOM?

A: A byte order mark (BOM) consists of the character code U+FEFF at the beginning of a data stream, where it can be used as a signature defining the byte order and encoding form, primarily of unmarked plaintext files. Under some higher level protocols, use
of a BOM may be mandatory (or prohibited) in the Unicode data stream defined in that protocol.

http://mindprod.com/jgloss/bom.html

BOM

Byte Order Marks are special characters at the beginning of a Unicode file to indicate whether it is big or little endian, in other words does the high or low order byte come first. These codes also tell whether the encoding is 8, 16 or 32 bit. You can recognise
Unicode files by their starting byte order marks, and by the way Unicode-16 files are half zeroes and Unicode-32 files are three-quarters zeros. Unicode Endian Markers

Byte-order mark Description

EF BB BF UTF-8

FF FE UTF-16 aka UCS-2, little endian

FE FF UTF-16 aka UCS-2, big endian

00 00 FF FE UTF-32 aka UCS-4, little endian.

00 00 FE FF UTF-32 aka UCS-4, big-endian.

There are also variants of these encodings that have an implied endian marker.

Unfortunately, often applications, even Javac.exe, choke on these byte order marks. Java Readers don't automatically filter them out. There is not much you can do but manually remove them.

http://cache.baidu.com/c?word=java%2Cbom&url=http%3A//tgdem530%2Eblogchina%2Ecom/&b=0&a=1&user=baidu

c、UTF的字节序和BOM

UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?

Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法:

在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。

这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。

Windows就是使用BOM来标记文本文件的编码方式的。

原来BOM是在文件的开始加了几个字节作为标记。有了这个标记,一些协议和系统才能识别。好,看看怎么加上这写字节。

终于在这里找到了

http://mindprod.com/jgloss/encoding.html 

UTF-8 

8-bit encoded Unicode. neé UTF8. Optional marker on front of file: EF BB BF for reading. Unfortunately, OutputStreamWriter does not automatically insert the marker on writing. Notepad can't read the file without this marker. Now the question is, how do you
get that marker in there? You can't just emit the bytes EF BB BF since they will be encoded and changed. However, the solution is quite simple. prw.write( '\ufeff' ); at the head of the file. This will be encoded as EF BB BF.

DataOutputStreams have a binary length count in front of each string. Endianness does not apply to 8-bit encodings. Java DataOutputStream and ObjectOutputStream uses a slight variant of kosher UTF-8. To aid with compatibility with C in JNI, the null byte '\u0000'
is encoded in 2-byte format rather than 1-byte, so that the encoded strings never have embedded nulls. Only the 1-byte, 2-byte, and 3-byte formats are used. Supplementary characters, (above 0xffff), are represented in the form of surrogate pairs (a pair of
encoded 16 bit characters in a special range), rather than directly encoding the character.

 

prw.write( '\ufeff' );就是这个。

于是我的代码变为:

public void htmlWrite(String charsetName) {

        try {

            out = new BufferedWriter(new OutputStreamWriter(

                        new FileOutputStream(outFileName), "UTF-8"));

            out.write('\ufeff');

            out.write(res);

            out.flush();

if (out != null) {

                out.close();

            }

        } catch (Exception e) {

            try {

                if (out != null) {

                    out.close();

                }

            } catch (IOException e1) {

                System.out.print("write errors!" + e);

            }

System.out.print("write errors!" + e);

        }

    }

问题解决。

本文出处:http://blog.sina.com.cn/s/blog_3e9d2b350100as0b.html

UTF-8 的BOM带来的麻烦的更多相关文章

  1. gcc编译器优化给我们带来的麻烦???

    gcc编译器优化给我们带来的麻烦??? 今天看到一个很有趣的程序,如下: ? 1 2 3 4 5 6 7 8 9 int main() {     const int a = 1;     int * ...

  2. utf 8无bom和utf 8什么区别

    今天在上传CSV文件的时候,Windows下调试一切正常.妈的一到Linux下面,就出现问题,第一行数据总是读取不出来, 利用print_r()打印出读取文件的内容,发现有一个很奇怪的字符在作怪.为什 ...

  3. 引入HBase依赖包带来的麻烦

    在一个项目里用到HBase做底层存储,使用maven来管理相关Jar包依赖,用maven来管理依赖包,特别不爽的就是他会将你引入Jar包自己的依赖都搞进来,经常会出现一些类和方法冲突找不到等状况.这次 ...

  4. json(gson) 转换html标签带来的麻烦

    gson 转换html标题时,会把html(特殊字符转换为unicode编码) ,所以为了避免这个问题GsonBuilder类 有一个 disablehtmlEscaping方法. 就可以让gson类 ...

  5. 关于结构化BOM的思考

    参加了今天的"自主生产音箱类产品BOM结构问题"(即非采购而是制造的音箱)会议,我发现大家在会议上呈现的产品结构对生产计划的层级需求已上升到5层的需求了,又找段会胜要了各位前期就此 ...

  6. BOM设计的一些问题及解决方案探讨----合版BOM

    BOM是ERP的核心资料,也是比较难的一块,不仅涉及的内容多,要求准确性高,时效性也要求高.但传统的ERP在处理BOM时有不少问题,因此也有些软件公司引入了各种BOM类型,像"标准BOM&q ...

  7. Ruby 对多语言的支持

    这是一篇翻译文章,原文链接 http://blog.grayproductions.net/articles/understanding_m17n.原文是一个系列,翻译过来整合成了一篇文章,对文章内容 ...

  8. 面试题<初级>

    INTERVIEW .markdown-body ul pre code { background:red; font-size:40px; } @code-char:"```" ...

  9. JS编程常识

    一.UI层的松耦合 松耦合就是要求各层遵循“最少知识原则”,或者说是各层各司其职,不要越权: HTML:结构层 CSS:表现层 JS:行为层 对于各层的职能,有一句比较贴切的解释:HTML是名词(n) ...

随机推荐

  1. python 字典操作方法详解

    字典是一种通过名字或者关键字引用的得数据结构,key 类型需要时被哈希,其键可以是数字.字符串.元组,这种结构类型也称之为映射.字典类型是Python中唯一內建的映射类型. 注意,浮点数比较很不精确, ...

  2. Notice!

    之后的小车内容在这里更新,开源社区,新浪博客不再更新.

  3. java中的二叉树排序问题

    原创:转载请注明出处 目的:想用java实现二叉树排序算法 思想:利用java中面向对象的思想,即: Tree:类 树根Tree:root //static所属于每一个Tree 左节点Tree:lef ...

  4. 前端 js技术

    1.JavaScript代码存在形式 <!-- 方式一 --> <script type"text/javascript" src="JS文件" ...

  5. 浅谈PHP异常处理

    1.PHP中异常的独特性 PHP中的异常的独特性,即PHP中的异常不同于主流语言C++.java中的异常.在Java中,异常是唯一的错误报告方式,而在PHP中却不是这样,而是把所有不正常的情况都视作了 ...

  6. JQuery Ajax 设置请求头信息application/json

    今天有个api后台接application/json格式的 在Jquery里$.ajax默认是contentType: application/x-www-form-urlencoded; chars ...

  7. 《Thinking in Java》学习笔记(三)

    1>Java中的常量 使用final和static来修饰的变量称为常量,常量用大写字母表示,字母间用下划线连接. Java中定义常量有以下几种方式: interface ConstantInte ...

  8. 学习H5仿制网站时遇到的问题

    学习H5的第二周,开始仿制网站,在本过程中也发现了自己存在的更多问题. 1.TOP块:在制作top中,遇到的第一个问题,一旦top左右的背景色不同该怎样去调整 解决方式:建立两个div取代一个div ...

  9. linux常用命令(不断更新)

    睡眠命令(第一步可省去): 1.查看你的系统支持什么模式:cat /sys/power/state(我的系统为:freeze mem disk) 2.切换到管理员模式下,执行命令:echo " ...

  10. WPF 使用DMSkin for WPF 快速搭建漂亮的WPF程序

    DMSkin-for-WPF是一个基于WPF的.Net WPF开源界面库,实现了无边框的WPF开发方案,内置部分控件模板. 你可以参照模板自行修改完善.(以下简称DFW). 核心 DFW实现了比较完美 ...