`
daimojingdeyu
  • 浏览: 274896 次
  • 性别: Icon_minigender_1
  • 来自: 山东
社区版块
存档分类
最新评论

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

    博客分类:
  • Java
阅读更多

最近在处理文件时发现了同样类型的文件使用的编码可能是不同的。所以想将文件的格式统一一下(因为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格式保存,则在使用程序读取是会从文件中多读出一个不可见字符。
测试代码如下:

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循环中可加入下面的代码,测试一下读出内容:

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/

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

BufferedReader br = new BufferedReader(new UnicodeReader(in, Charset.defaultCharset().name()));


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

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

 

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

 

分享到:
评论
11 楼 qiuqi314 2013-08-28  
折腾了我半天,终于找到解决方法了。。。 
10 楼 hanyu332 2013-01-10  
daimojingdeyu 写道
hanyu332 写道
要是java代码以这个开头,该怎么解决呢?

你遇见了什么问题呢?

当时是,网上下的开发包,类文件前面带有这个东西,导致程序运行报错,现在已经解决了
9 楼 daimojingdeyu 2012-08-11  
hanyu332 写道
要是java代码以这个开头,该怎么解决呢?

你遇见了什么问题呢?
8 楼 hanyu332 2012-08-10  
要是java代码以这个开头,该怎么解决呢?
7 楼 feng5199 2011-03-07  
非常感谢LZ
6 楼 daimojingdeyu 2011-02-18  
charseller 写道
奶奶个熊!耽搁了我1天!!多谢经验交流

共同进步!
5 楼 charseller 2011-02-18  
奶奶个熊!耽搁了我1天!!多谢经验交流
4 楼 daimojingdeyu 2010-08-15  
snoopy3384 写道
很好,很强大,谢谢

3 楼 snoopy3384 2010-06-24  
很好,很强大,谢谢
2 楼 daimojingdeyu 2009-09-13  
pptztf 写道
楼主,弄了一中午转码,你的贴惊醒了我,呵呵,这是一篇好贴啊。。

看到这篇帖子对你有帮助,我也很开心~~~
1 楼 pptztf 2009-09-12  
楼主,弄了一中午转码,你的贴惊醒了我,呵呵,这是一篇好贴啊。。

相关推荐

    Java解决UTF-8的BOM问题

    本文将深入探讨如何使用Java来处理带有BOM的UTF-8文件。 首先,`UnicodeInputStream`和`UnicodeReader`是Java中用于处理Unicode编码流的类。它们是`java.io`包的一部分,提供了对带有BOM的文件进行读取的功能。`...

    java 读取服务器上的某个文件,并解决UTF-8 BOM文件的问号问题

    这个场景中,我们面临的挑战是如何正确处理UTF-8带有BOM(Byte Order Mark)的文件,因为BOM可能会导致文件内容显示为问号或者其他乱码。下面将详细介绍如何解决这个问题。 首先,我们需要理解什么是UTF-8的BOM。...

    java读写csv文件,中文乱码问题

    4. **处理BOM头**:UTF-8有带BOM和不带BOM两种形式,如果文件开头带有BOM标记,可能需要在读取时进行特殊处理,因为某些库可能不支持带BOM的UTF-8。 5. **使用第三方库**:有一些Java库,如OpenCSV、Apache Commons...

    java去掉txt文本的bom头信息

    以下是一个简单的示例,展示了如何读取带有BOM头的UTF-8文件,并将其写入一个新的不带BOM头的文件: ```java import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; ...

    Java读取中文文件出现乱码解决过程.mht

    7. **注意文件的BOM头**:有些UTF-8编码的文件带有BOM(Byte Order Mark),在读取时如果不考虑BOM,也可能导致乱码。可以使用无BOM的UTF-8编码进行读取。 总之,解决Java读取中文文件乱码的关键在于确定正确的文件...

    深入UTF8字符编码

    - BOM(Byte Order Mark):UTF-8编码的文件可以带有一个可选的BOM标记,用于指示数据流的字节顺序,但某些工具或程序可能不支持带BOM的UTF-8。 - 乱码问题:检查文件读取和写入时的编码设置,确保一致。 - 汉字全角...

    java读取文件免除乱码

    例如,UTF-8编码的文件如果带有BOM(Byte Order Mark),则可以通过检查其前三个字节是否为` EF BB BF`来判断。 在实际项目中,我们还需要注意以下几点: - 在处理未知编码的文件时,可以尝试多种常见编码进行读取...

    什么是BOM头,如何去掉BOM头.zip

    针对BOM头可能导致的页面顶部空白一行的问题,可以检查HTML文件是否带有BOM头,如果是,则按照上述方法去除。在PHP开发中,如果遇到因BOM头导致的隐形字符问题,可以使用上述方法去除BOM,或者在代码处理文件前先...

    SourceInsight乱码解决方案

    如果文件是UTF-8带BOM的,那么可能需要转换为无BOM的UTF-8或更改SourceInsight的配置以适应BOM编码。 2. **修改SourceInsight配置**:打开SourceInsight,进入“Options”(选项)菜单,选择“File Encoding”...

    JSP乱码终极攻略和AJAX初步运用

    这是因为UTF-8编码的中文字符在传输时会带有字节顺序标记(BOM),即`EF BB BF`,在解码时如果不正确处理,会导致解码失败。 为了解决这个问题,可以在服务器端的Tomcat配置中设置`URIEncoding="UTF-8"`,并在...

    BOM结构的更改标记不显示问题

    标题中的“BOM结构的更改标记不显示问题”是指在处理文本文件时,尤其是在编码格式为UTF-8的情况下,出现的Byte Order Mark (BOM) 不被正确显示或识别的问题。BOM是一个特殊的字符序列,用于标识文件是以UTF-8编码的...

    poi3.7支持中文编码

    在Java中,使用InputStreamReader和OutputStreamWriter与特定的字符编码(如"UTF-8")结合,可以确保数据读写时的正确编码。例如,当打开一个Excel文件时,可以设置适当的字符集来避免乱码: ```java InputStream ...

    SQLite数据库学习

    - 在处理CSV文件时,注意文件的BOM头(Byte Order Mark),某些程序可能无法正确处理带有BOM头的UTF-8文件,因此在转换或导入前,可以考虑去除BOM。 - 如果是程序内部存储的数据出现乱码,检查代码中对字符串编码和...

    获取编码格式的工具类

    常见的检测策略有BOM(Byte Order Mark)检查,对于UTF-16、UTF-8带有BOM的编码,可以通过首几个字节快速确定;对于无BOM的编码,可以使用诸如“频度统计”、“字节模式匹配”等方法进行推测。 2. **转换文件编码**...

    字节编码1

    如果在Eclipse中将Java源文件的编码从GBK改为UTF-8,而原始文件实际上是GBK编码的,那么在读取时就可能出现乱码,因为使用了错误的解码方式。 总结来说,字符编码涉及字符集、编码方案、字节流等多个层面,理解这些...

    批量修改TXT文档编码

    - **处理BOM头**:UTF-8有带BOM(Byte Order Mark)和不带BOM两种形式,根据需求选择合适的保存方式。 总的来说,批量修改TXT文档编码是一项常用但需谨慎的任务。正确理解和使用工具,能够有效解决编码不匹配带来的...

    新编码转换大全模块+应用例程.rar

    - **BOM(Byte Order Mark)**:UTF-8编码的文件可能会带有BOM,某些程序可能会因此出现问题。 - **处理策略**:确保文件编码信息的准确传递,或使用能自动识别编码的工具。 5. **应用例程**: 提供的应用例程...

    poi_java_excel.zip_java 导出excel_poi excel_poi导出再导入excel中文_导出exce

    如果你的Excel文件以UTF-8 BOM格式保存,那么在读取时可能需要进行额外处理,去除BOM标志。 此外,如果你需要在导入Excel数据后进行处理,例如数据库操作,你可能需要对数据进行转换和验证。Apache POI允许你访问...

    java字节字符转换流操作详解

    - UTF-8编码有两种形式:带BOM(Byte Order Mark)和不带BOM。BOM用于标识文件的编码格式,占用3个字节(0xEF 0xBB 0xBF)。在某些情况下,如使用文本编辑器创建的文件,是否包含BOM会影响文件大小和处理方式。 5....

Global site tag (gtag.js) - Google Analytics