最近在处理文件时发现了同样类型的文件使用的编码可能是不同的。所以想将文件的格式统一一下(因为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编程语言中,编码转换是一项重要的任务,特别是在处理不同来源的数据时,如读取文本文件、网络数据传输或数据库交互。...通过深入研究和实践,可以增强对Java编码转换机制的理解,提升软件质量。
本文将深入探讨“Java文件的编码转换”这一主题,以及如何利用Java来解决由于不同编码格式引起的兼容性问题。 首先,我们需要理解什么是文件编码。文件编码是指在计算机中存储和处理文本的方式,常见的有GBK和UTF-8...
在Java编程环境中,字符...总结来说,Java中字符编码的处理涉及多个层面,包括数据库连接、网页编码声明、文件读写等。通过正确配置和编码转换,可以有效解决中文显示问题,确保应用程序在不同编码环境下均能正常运行。
本教程将聚焦于如何使用原生Java 8来实现对西门子S7系列PLC的读写操作,而无需依赖任何DLL(动态链接库)文件,确保了程序的平台独立性和纯粹性。 首先,我们要理解S7协议。西门子的S7协议是用于其PLC产品通信的一...
Java 读写锁是Java并发编程中的一种重要机制,它为多线程环境下的数据访问提供了更为精细的控制。在Java的`java.util.concurrent.locks`包中,`ReentrantReadWriteLock`类实现了读写锁的功能。这个锁允许多个读取者...
Java的`FileInputStream`和`FileOutputStream`在读写文件时默认使用平台的默认编码。要指定特定编码,可使用`InputStreamReader`和`OutputStreamWriter`,如`new InputStreamReader(fileInputStream, "UTF-8")`。 ...
总结来说,Java提供了一种有效的方法来批量转换文件编码,只需指定文件路径、编码类型以及适当的读写工具。这使得开发者能够轻松地在不同的编码格式之间切换,确保数据在各种系统和环境下的兼容性。在实际项目中,...
这里提供的jar文件`hdf5-3.3.2.jar`是Java接口库,它封装了对HDF5文件的操作,使得Java程序员可以通过调用Java API来实现读写HDF5文件。而`libjhdf.so.3.2.1`和`jhdf5.dll`分别是Linux和Windows平台的动态链接库,...
java读写Modbus TCP UDP数据,java与modbus通信,Modbus TCP UDP与java通信 全开源 这是一个能正常通过Modbus TCP UDP协议读写项目 请放心下载,完全开源,在多个项目中已经使用
Java读写文件-Excel
在处理文件时,如果不指定编码,Java会使用平台默认的编码,这可能导致在不同平台上读写文件时出现乱码问题。因此,`ReadFile.java`这个源码文件很可能包含了读取文件时指定编码的逻辑。例如,使用`BufferedReader`...
最近在研究处理java写modbus RTU通信,分别使用几套工具,模拟modbus从站、模拟串口等才能正常在电脑测试成功。 全开源,放心下载 可以查看运行内容https://blog.csdn.net/weijia3624/article/details/121216539
在Java编程语言中,读写文本文件是常见的操作。这里我们详细探讨了四种不同方法来读取文本文件:按字节读取、按字符读取、按行读取以及随机读取。 1. **按字节读取文件内容**: 这种方法通常适用于读取二进制文件...
`Charset`可以用来编码(字符串转字节)和解码(字节转字符串)。Java默认支持多种常见的字符集,如ASCII、UTF-8、GBK等。 #### 文件读写操作 在Java中,读取和写入文件通常有两种方式:流式操作(使用`...
Java字符编码转换是Java开发中一个重要的概念,涉及到数据的正确读取、存储和传输。在Java中,编码转换通常发生在以下几个场景: 1. **JVM启动与系统属性**: JVM启动时,会根据操作系统的环境设置一些系统属性,...
1. **Java I/O流**:在读写文件时,Java的I/O流扮演着核心角色。`java.io`包提供了多种类,如`FileInputStream`用于读取文件,`FileOutputStream`用于写入文件。在处理docx到PDF转换时,你需要先读取docx文件的内容...
java通过snakeyaml类能非常方便的操作,读写yaml文件。
java读写pdf文件,教程文档都有,用读写pdf文件的方式做表格显示与打印效果很不错
在Java编程语言中,修改文件编码是一项常见的任务,特别是在处理不同源代码或数据文件时。本文将深入探讨如何使用Java来实现这一功能,主要关注以下几个关键知识点: 1. **字符编码的理解**:字符编码是将字符与二...
以下是一份详细的知识点解析,将帮助你理解和应用Java中的文件读写操作。 1. **Java I/O 基础** Java 提供了丰富的I/O API,主要位于`java.io`包下。核心类包括`File`, `InputStream`, `OutputStream`, `Reader`, ...