最近在处理文件时发现了同样类型的文件使用的编码可能是不同的。所以想将文件的格式统一一下(因为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);
-
-
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);
-
-
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)的源码放在了附件中
编码一直在困扰着我,这边文章比较经典,情不自禁(转)了:
转自:http://daimojingdeyu.iteye.com/blog/397661
分享到:
相关推荐
java读写xml文件 java读写xml文件 java读写xml文件 java读写xml文件 java读写xml文件 java读写xml文件
使用java8 scoket 实现西门子s7协议 可以读写 s7系列全部plc 没有dll 文件 纯原生java
Java 读写Ini文件,java读写ini文件的项目小例子。 运行类文件在根目录ini文件夹下src/com文件夹中start.java文件 相关jar包在根目录ini文件夹下bin文件夹中
JAVA读写二进制文件
java 读写锁实例代码,付简单注释,测试完整。
java读写properties配置文件
java文件读写操作大全java文件读写操作大全java文件读写操作大全java文件读写操作大全java文件读写操作大全
java读写excel文件,新手参考高手绕道。
java 读写word 转html 等操作实例及jar包
压缩包中包含java读写hdf5格式文件时需要的jar包和动态链接库,动态链接库提供了windows、linux两种版本的
Java读写文件-Excel
JAVA简单的读写文本文件的代码JAVA简单的读写文本文件的代码
java通过snakeyaml类能非常方便的操作,读写yaml文件。
Java 读写文件文本文件的示例
java读写xml的代码
Java读写文本文件的示例代码 这个例子可以帮助JAVA爱好者理解JAVA对文件的操作,打开、删除、写入等操作。对初学者很有帮助。
Java 操作Excel poi读写excel,所需要的jar包 https://blog.csdn.net/u014646662/article/details/83217382
java 随机读写Java类文件 java 随机读写Java类文件 java 随机读写Java类文件
java读写pdf文件,教程文档都有,用读写pdf文件的方式做表格显示与打印效果很不错
Java读写文本文件的示例代码.rar