UTF-8 的BOM带来的麻烦
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带来的麻烦的更多相关文章
- gcc编译器优化给我们带来的麻烦???
gcc编译器优化给我们带来的麻烦??? 今天看到一个很有趣的程序,如下: ? 1 2 3 4 5 6 7 8 9 int main() { const int a = 1; int * ...
- utf 8无bom和utf 8什么区别
今天在上传CSV文件的时候,Windows下调试一切正常.妈的一到Linux下面,就出现问题,第一行数据总是读取不出来, 利用print_r()打印出读取文件的内容,发现有一个很奇怪的字符在作怪.为什 ...
- 引入HBase依赖包带来的麻烦
在一个项目里用到HBase做底层存储,使用maven来管理相关Jar包依赖,用maven来管理依赖包,特别不爽的就是他会将你引入Jar包自己的依赖都搞进来,经常会出现一些类和方法冲突找不到等状况.这次 ...
- json(gson) 转换html标签带来的麻烦
gson 转换html标题时,会把html(特殊字符转换为unicode编码) ,所以为了避免这个问题GsonBuilder类 有一个 disablehtmlEscaping方法. 就可以让gson类 ...
- 关于结构化BOM的思考
参加了今天的"自主生产音箱类产品BOM结构问题"(即非采购而是制造的音箱)会议,我发现大家在会议上呈现的产品结构对生产计划的层级需求已上升到5层的需求了,又找段会胜要了各位前期就此 ...
- BOM设计的一些问题及解决方案探讨----合版BOM
BOM是ERP的核心资料,也是比较难的一块,不仅涉及的内容多,要求准确性高,时效性也要求高.但传统的ERP在处理BOM时有不少问题,因此也有些软件公司引入了各种BOM类型,像"标准BOM&q ...
- Ruby 对多语言的支持
这是一篇翻译文章,原文链接 http://blog.grayproductions.net/articles/understanding_m17n.原文是一个系列,翻译过来整合成了一篇文章,对文章内容 ...
- 面试题<初级>
INTERVIEW .markdown-body ul pre code { background:red; font-size:40px; } @code-char:"```" ...
- JS编程常识
一.UI层的松耦合 松耦合就是要求各层遵循“最少知识原则”,或者说是各层各司其职,不要越权: HTML:结构层 CSS:表现层 JS:行为层 对于各层的职能,有一句比较贴切的解释:HTML是名词(n) ...
随机推荐
- ------- 软件调试——挫败 QQ.exe 的内核模式保护机制 -------
------------------------------------------------------------------------ QQ 是一款热门的即时通信(IM)类工具,在安装时刻会 ...
- js、jQuery实现2048小游戏
2048小游戏 一.游戏简介: 2048是一款休闲益智类的数字叠加小游戏 二. 游戏玩法: 在4*4的16宫格中,您可以选择上.下.左.右四个方向进行操作,数字会按方向移动,相邻的两个数字相同就会合 ...
- ABP官方文档翻译 7.1 后台Jobs和Workers
后台Jobs和Workers 介绍 后台Jobs 关于Job持久化 创建后台Job 在队列中添加一个新Job 默认的后台Job管理器 后台Job存储 配置 禁用Job执行 异常处理 Hangfire集 ...
- 洛谷 [P1220] 关路灯
本题是一道区间DP,很容易设计出状态, dp[i][j]代表关掉i到j的路灯所耗的电量,但是对于新到一个路灯来说,可以是原来直接来的,也可以是掉头来的,于是还需要添加一维 0代表在区间的左端,1代表在 ...
- bzoj 4870: [Shoi2017]组合数问题 [矩阵乘法优化dp]
4870: [Shoi2017]组合数问题 题意:求 \[ \sum_{i=0}^{n-1} \binom{nk}{ik+r} \mod p \] \(n \le 10^9, 0\le r < ...
- CF 246E. Blood Cousins Return [dsu on tree STL]
题意: 一个森林,求k级后代中多少种不同的权值 用set维护每个深度出现的权值 一开始一直在想删除怎么办,后来发现因为当前全局维护的东西里都是当前子树里的,如果要删除那么当前一定是轻儿子,直接清空se ...
- python语言基础汇总
注释 代码中添加注释是一个良好的编程习惯,python语言的注释才用井号'#'作为注释开头的,可以是任意内容,解释器会忽略掉这部分内容.其他每一行都是语句,当语句以冒号':'结尾时,缩进的语句视为代码 ...
- Flask-Moment----探索
前言: Flask-Moment在所有的flask扩展中算是相对简单的一个了,但是还是有很多需要理解的地方.那么今天就跟着笔者一起,来学习一下flask-moment在flask项目中的应用. 首先 ...
- servlet上传与下载
上传页面 上传学生信息 学号 姓名 密码 性别 男 女 年龄 身高 学院 计算机学院 软件学院 照片 简历 <!DOCTYPE html> <html lang=&qu ...
- AnnotationUtils
/** * 查询类中符合指定annotation的属性信息 * @param objCls 实体类 * @param annCls 注解类 * @return HashMap<实体属性名, An ...