您的位置:首页 > 编程语言 > Java开发

JAVA输出带BOM的UTF-8编码的文件

2016-01-12 14:23 447 查看
当从http 的response输出CSV文件的时候,设置为utf8的时候默认是不带
bom的,但是windows的Excel是使用bom来确认utf8编码的,所有需要把bom写到文件的开头。
微软在 UTF-8 中使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码明确区分开。
否则用Excel打开CSV文件有可能是乱码的
示例代码如下:
response.setContentType("text/csv");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.setCharacterEncoding("UTF-8");
byte[] uft8bom={(byte)0xef,(byte)0xbb,(byte)0xbf};
OutputStream out = response.getOutputStream();
out.write(uft8bom);

OutputStreamWriter writer = new OutputStreamWriter(out,"UTF-8");

//write other content ...

什么是BOM:
BOM(byte-order mark),即字节顺序标记,它是插入到以UTF-8、UTF16或UTF-32编码Unicode文件开头的特殊标记,用来识别Unicode文件的编码类型。对于UTF-8来说,BOM并不是必须的,因为BOM是用来标记多字节编码文件的编码类型和字节顺序(big-endian或little- endian)。而UTF8中,每个字符的编码有多少位是通过第一个字节来表述的,而且没有big-endian和little-endian的区分,见后述。

BOMs 文件头:
   00 00 FE FF    = UTF-32, big-endian
   FF FE 00 00    = UTF-32, little-endian
   EF BB BF       = UTF-8,
   FE FF          = UTF-16, big-endian
   FF FE          = UTF-16, little-endian

还有一个要注意的是:UTF-8 的网页代码不应使用 BOM,否则常常会出错:
在网页上使用BOM是个错误。BOM设计出来不是用来支持HTML和XML的。要识别文本编码,HTML有charset属性,XML有encoding属性,没必要拉BOM撑场面。虽然理论上BOM可以用来识别UTF-16编码的HTML页面,但实际工程上很少有人这么干。毕竟UTF-16这种编码连ASCII都双字节,实在不适用于做网页。

Windows使用BOM的历史原因:
通常BOM是用来标示Unicode纯文本字节流的,用来提供一种方便的方法让文本处理程序识别读入的.txt文件是哪个Unicode编码(UTF-8,UTF-16BE,UTF-16LE)。Windows相对对BOM处理比较好,是因为Windows把Unicode识别代码集成进了API里,主要是CreateFile()。打开文本文件时它会自动识别并剔除BOM。Windows用这个有历史原因,因为它最初脱胎于多代码页的环境。而引入Unicode时Windows的设计者又希望能在用户不注意的情况下同时兼容Unicode和非Unicode(Multiple byte)文本文件,就只能借助这种小trick了。

带BOM的文本文件在Linux/unix环境又经常会遇到问题:
知乎介绍的很详细: http://www.zhihu.com/question/20167122
文本文件解析:     
文本文件对应于人类可以阅读的文本,如何从2进制转换为文本文件呢?起初由于计算机在美国发明,自然大家考虑的是英语如何表示,英语字母总共26个,加上特殊字符,128个字符,7位既一个byte即可表示出来。这个就是大家所熟知的ascill编码。对应关系很简单,一个字符对应一一个byte。     但很快发现,其他非英语国家的文字远远超过ascill码,这时候大家当然想统一一下,不同国家出了自己不同的编码方式,中国的gb2312就是自己做出来的编码方式,这样下去每个国家都有自己的编码方式,来回转换太麻烦了。这时候出现了新的编码方式,unicode编码方式,想将编码统一,所以规定了每个字符对应的unicode码。     1、很多文件都是ascii编码,如果用unicode 太浪费。     2、没有标志位说明该几个字节来解析为一个符号。     这时候拯救世界的utf出现了,utf是unicode的一种实现,只不过更聪明了。utf16是占用两字节,或者四字节,utf32是占用四字节。utf8是很聪明的一种表示方式。     
1、对于单字节符号,字节第一位为0,后面7位表示字节编码。     
2、对于n字节符号,第一字节的前n位都设为1,第n+1位为0,其余位用于编码。
对于不同的编码,在文本的最前方有不同的标志,unicode 通常有两位来表示分别是ff fe, 或者feff, fffe表示litte-endian 编码feff表示big-endian编码。
utf8是efbbbf来开头的。可以看出来utf-8是自解释的,所以不用带这个标志文件,大多数程序是可以识别的。但有些程序不能识别这个标志,比如php就会直接把这个标志当文本解析,不会忽略。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JAVA UTF8 BOM