Reader 类是 Java 的 I/O 中读字符的父类,而 InputStream 类是读字节的父类,InputStreamReader 类就是关联字节到字符的桥梁,它负责在 I/O 过程中处理读取字节到字符的转换,而具体字节到字符的解码实现它由 StreamDecoder 去实现,在 StreamDecoder 解码过程中必须由用户指定 Charset 编码格式。值得注意的是如果你没有指定 Charset,将使用本地环境中的默认字符集,例如在中文环境中将使用
GBK 编码。
Java以二进制字节方式读写文件时,不会有乱码的问题。(示例代码使用了缓存BufferedInputStream和BufferedOutputStream)
@Test public void testFileByBytes() { FileInputStream fis = null; BufferedInputStream bis = null; FileOutputStream fos = null; BufferedOutputStream bos = null; try { fis = new FileInputStream("d:/Work/readme.txt"); bis = new BufferedInputStream(fis); fos = new FileOutputStream("d:/Work/readme_bytes.txt"); bos = new BufferedOutputStream(fos); int c = 0; byte[] buf = new byte[512]; while((c = bis.read(buf)) != -1) { bos.write(buf, 0, c); } } catch (Exception e) { e.printStackTrace(); } finally { close(bis); close(bos); } }
写的情况也是类似,字符的父类是 Writer,字节的父类是 OutputStream,通过 OutputStreamWriter 转换字符到字节。
2. Java以字符方式读写文本文件时,则有可能会出现乱码。(如下示例代码指定编码格式为GBK。如果不指定编码则可能会出现中文字符乱码的问题,原因是在未明确指定字符编码的情况下,Java默认使用ISO-8859-1进行编码,从而使所有的中文字符被?所替代)
注:FileWriter/FileReader是分别继承自InputSteamReader/OutputStreamWriter实现的,不能指定字符编码。因此文本文件中有中文字符时,不建议使用。
- @Test
- public void testFileByChars()
- {
- InputStreamReader isr = null;
- OutputStreamWriter osw = null;
- try
- {
- FileInputStream fis = new FileInputStream("d:/Work/readme.txt");
- isr = new InputStreamReader(fis, Charset.forName("GBK"));
- FileOutputStream fos = new FileOutputStream("d:/Work/readme_chars.txt");
- osw = new OutputStreamWriter(fos, Charset.forName("GBK"));
- char[] cbuf = new char[512];
- int c = 0;
- while((c = isr.read(cbuf)) != -1)
- {
- osw.write(cbuf, 0, c);
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- finally
- {
- close(isr);
- close(osw);
- }
- }
http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/index.html