Java读带有BOM的UTF-8文件乱码原因及解决方法

Java读带有BOM的UTF-8文件乱码原因及解决方法 - daimojingdeyu - ITeye技术网站

Java读带有BOM的UTF-8文件乱码原因及解决方法

博客分类:Java

JavaJVMJDKF#

最近在处理文件时发现了同样类型的文件使用的编码可能是不同的。所以想将文件的格式统一一下(因为UTF-8的通用性,决定往UTF-8统一),遇见的第一个问题是:如何查看现有文件的编码方式。

上网找了一下,找到几篇比较好文章,这里就不转载啦把链接搞过来。
文件编码问题集锦

字符串编码(charset,encoding,decoding)问题原理

Java编码浅析

判定文件编码或文本流编码的方法

上面的几篇文章可以看成认识编码问题的“从入门到精通”

如果你看完了上面的文章,一定了解到了,在java中,class文件采用utf8的编码方式,JVM运行时采用utf16。Java的字符串是永远都是unicode的,采用的是UTF-16的编码方式。

想测试一下,java对UTF-8文件的读写的能力,结果发现了一个很郁闷的问题,如果通过java写的UTF-8文件,使用Java可以正确的读,但是如果用记事本将相同的内容使用UTF-8格式保存,则在使用程序读取是会从文件中多读出一个不可见字符。

测试代码如下:

Java代码  
  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStreamReader;
  6. public class UTF8Test {
  7. public static void main(String[] args) throws IOException {
  8. File f  = new File("./utf.txt");
  9. FileInputStream in = new FileInputStream(f);
  10. // 指定读取文件时以UTF-8的格式读取
  11. BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
  12. String line = br.readLine();
  13. while(line != null)
  14. {
  15. System.out.println(line);
  16. line = br.readLine();
  17. }
  18. }
  19. }
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;public class UTF8Test {public static void main(String[] args) throws IOException {File f  = new File("./utf.txt");FileInputStream in = new FileInputStream(f);// 指定读取文件时以UTF-8的格式读取BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));String line = br.readLine();while(line != null){System.out.println(line);line = br.readLine();}}
}

utf.txt通过记事本创建,另存时使用指定utf-8编码,其内容为:

引用

This is the first line.

This is second line.

正常的测试结果应该是直接输出utf.txt的文本内容。可是实际上却输出了下面的内容:

引用

?This is the first line.

This is second line.

第一行多出了一个问号。

通过上面的几篇文章应该可以想到是Java读取BOM(Byte Order Mark)的问题,在使用UTF-8时,可以在文件的开始使用3个字节的"EF BB BF"来标识文件使用了UTF-8的编码,当然也可以不用这个3个字节。

上面的问题应该就是因为对开头3个字节的读取导致的。开始不太相信这个是JDK的Bug,后来在多次试验后,问题依然存在,就又狗狗了一下,果然找到一个如下的Bug:
Bug ID:4508058

不过在我关掉的一些页面中记得有篇文件说这个bug只在jdk1.5及之前的版本才有,说是1.6已经解决了,从目前来看1.6只是解决了读取带有BOM文件失败的问题,还是不能区别处理有BOM和无BOM的UTF-8编码的文件,从Bug ID:4508058里的描述可以看出,这个问题将作为一个不会修改的问题关闭,对于BOM编码的识别将由应用程序自己来处理,原因可从另处一个bug处查看到,因为Unicode对于BOM的编码的规定可能发生变化。也就是说对于一个UTF-8的文件,应用程序需要知道这个文件有没有写BOM,然后自己决定处理BOM的方式。

在上面的while循环中可加入下面的代码,测试一下读出内容:

Java代码  
  1. byte[] allbytes = line.getBytes("UTF-8");
  2. for (int i=0; i < allbytes.length; i++)
  3. {
  4. int tmp = allbytes[i];
  5. String hexString = Integer.toHexString(tmp);
  6. // 1个byte变成16进制的,只需要2位就可以表示了,取后面两位,去掉前面的符号填充
  7. hexString = hexString.substring(hexString.length() -2);
  8. System.out.print(hexString.toUpperCase());
  9. System.out.print(" ");
  10. }
byte[] allbytes = line.getBytes("UTF-8");for (int i=0; i < allbytes.length; i++){int tmp = allbytes[i];String hexString = Integer.toHexString(tmp);// 1个byte变成16进制的,只需要2位就可以表示了,取后面两位,去掉前面的符号填充hexString = hexString.substring(hexString.length() -2);System.out.print(hexString.toUpperCase());System.out.print(" ");}

输出结果如下:

引用

EF BB BF
54 68 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20 6C 69 6E 65 2E

?This is the first line.

54 68 69 73 20 69 73 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E

This is second line.

红色部分的"EF BB BF"刚好是UTF-8文件的BOM编码,可以看出Java在读文件时没能正确处理UTF-8文件的BOM编码,将前3个字节当作文本内容来处理了。

使用链接中提供的代码可以解决碰到的乱码问题:
http://koti.mbnet.fi/akini/java/unicodereader/

修改测试代码中的输入流后:

Java代码  
  1. BufferedReader br = new BufferedReader(new UnicodeReader(in, Charset.defaultCharset().name()));
BufferedReader br = new BufferedReader(new UnicodeReader(in, Charset.defaultCharset().name()));

执行,可以看到正确的结果。

将用到的测试代码及UTF-8读取乱码解决(http://koti.mbnet.fi/akini/java/unicodereader)的源码放在了附件中

累了,去 淘宝皇冠店铺
看看

  • code.zip (3 KB)
  • 下载次数: 796
posted on 2012-03-12 11:33 lexus 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lexus/archive/2012/03/12/2391510.html

Java读带有BOM的UTF-8文件乱码原因及解决方法相关推荐

  1. Java读带有BOM的UTF-8文件乱码原因及解决方法(转)

    转载:http://www.linuxidc.com/Linux/2012-12/76707.htm 最近在处理文件时发现了同样类型的文件使用的编码可能是不同的.所以想将文件的格式统一一下(因为UTF ...

  2. Java读取UTF-8格式txt文件第一行出现乱码及解决;Java读带有BOM的UTF-8文件乱码原因及解决方法(转载)...

    原文地址:http://blog.csdn.net/jackpk/article/details/5702964/ Java读取UTF-8的txt文件第一行出现乱码"?"及解决 t ...

  3. java delete file 失败_file.delete()无法删除文件的原因及解决方法

    file.delete()无法删除文件的原因及解决方法 发布时间:2020-05-06 09:41:00 来源:亿速云 阅读:756 作者:小新 今天小编给大家分享的是file.delete()无法删 ...

  4. 系统错误计算机中丢失文件,电脑文件丢失了怎么办?电脑文件丢失原因以及解决方法都在这了!...

    原标题:电脑文件丢失了怎么办?电脑文件丢失原因以及解决方法都在这了! 现在人们的数据保护意识是越来越强了,就前阵子的英特尔漏洞事件,其实人们更关心的不是电脑变慢,而是电脑中的数据隐私泄露.虽然现在人们 ...

  5. /var/spool/clientmqueue目录下存在大量文件的原因及解决方法

    /var/spool/clientmqueue目录下存在大量文件的原因及解决方法 参考文章: (1)/var/spool/clientmqueue目录下存在大量文件的原因及解决方法 (2)https: ...

  6. Java并发--ConcurrentModificationException(并发修改异常)异常原因和解决方法

    Java并发--ConcurrentModificationException(并发修改异常)异常原因和解决方法 参考文章: (1)Java并发--ConcurrentModificationExce ...

  7. log4j日志文件乱码问题的解决方法

    log4j日志文件乱码问题的解决方法 log4j日志文件中文乱码处理方法 log4j 控制台和文件输出乱码问题解决 写在前面,第三篇文章中将原因解释的最清楚,为什么设置为UTF-8或者GBK就生效了, ...

  8. 电脑浏览器打不开html文档,win7浏览器打不开本地html文件的原因及解决方法

    今天小编和大家分享深度技术win7系统浏览器打不开本地html文件的原因及解决方法,相信大家都有遇到过html文件打不开,一直显示主页而不是html页面,其实很大部分是浏览器设置问题.有什么办法可以解 ...

  9. 3d缺少html文件,3dmax打开时显示缺少外部文件的原因及解决方法

    为什么每次打开3DMAX都显示缺少外部文件?在做3dmax模型贴图或者下载模型之后,经常会出现缺少外部文件的情况,这是怎么回事?遇到这一情况又该如何解决呢?接下来小编就给大家整理了用3dmax打开模型 ...

最新文章

  1. Linux Wi-Fi 编程API介绍
  2. PHP 删除数组中元素的方式
  3. 推荐8个高质量的小众实用APP,解决你的痛点需求
  4. NBT:用16S及18S rRNA全长进行微生物多样性研究
  5. 为什么要学数学?因为这是一场战略性的投资
  6. 云平台项目实战(华为篇)之存储技术
  7. 【转载】java中Date与String的相互转化
  8. 57. mysqli 扩展库(4)
  9. Oracle Study之-- enq:SQ contention等待事件
  10. 【Vue: 使用pdf.js顯示PDF Viewer】
  11. 自动化测试框架基石工程
  12. html5版微博qq登录,QQ和新浪微博登陆第三方的简单实现
  13. 地铁线路查询(easyx)
  14. Chrome扩展、装逼神器:Vimium
  15. HTML onfocus (获得焦点)和 onblur (失去焦点)
  16. 18. Redis 管理命令-查看服务器状态
  17. 逻辑回归实例,特征预处理
  18. Android布局优化
  19. 红色印章制作过程记录
  20. 【模拟器】华为模拟器eNSP安装注意事项及常见报错处理

热门文章

  1. qsql 关联_怎样在Qt下连接读写sqlite数据库
  2. 态势感知与信质、信量
  3. python打印小票_pyqt5 商店小票打印的实现模板
  4. 留学生福利!超好用免费英文论文润色软件Wordvice AI上线啦
  5. 神奇的计算机网络教案,网络信息技术教案
  6. 在微信小程序使用外部字体
  7. 企业如何进行中台的架构与数据模型的管控?
  8. 封装BigDecimal的加减乘除方法,保留自定义位小数的工具。
  9. TX2+倍加福r2000运行例程调试
  10. java计算机毕业设计至臻阁古董拍卖网源码+数据库+系统+lw文档+mybatis+运行部署