Java IO 与 编码 浅析,希望大家多多指教

这些天,研究了下java IO与编码相关的问题,希望和大家探讨一下,欢迎拍砖,共同提高。
可以转载,但是请表明原作者 mubing_s。

首先我们都知道,java IO 的输入流顶层类有两个: java.io.Reader(字符流) 和 java.io.InputStream(字节流),本文要做的是深入细节来解析字符流和字节流在处理文本读入时到底是怎么做的。

先请移步看个小代码:
package learn;
import java.io.*;
class Go{
	public static void main(String args[]) throws FileNotFoundException, IOException{
		FileReader fr = new FileReader("xx.txt");
		//System.out.println(fr.getEncoding());
		int num;
		while((num = fr.read()) != -1){
			System.out.println(Integer.toHexString(num));
		}
		fr.close();
		
		System.out.println("--------------------");
		
		int get_num;
		FileInputStream fis = new FileInputStream("xx.txt");
		while((get_num = fis.read()) != -1){
			System.out.println(Integer.toHexString(get_num));
		}
		fis.close();
	}
}




现在我们的xx.txt假设内容就是一个中文字:我
我们可以在中文编码在线查询网站http://ipseeker.cn/tools/pywb.php中看到:



以上程序运行的结果是FileInputStream fis 的输出结果是 ced2,这就是说明我们的txt文本采用的是gbk的编码,因为fis是InputStream(字符流),所以对它来说根本不认识编码,它只是简单的把txt里面的内容(其实就是二进制串)抄了进来。

下面说FileReader,FileReader 是InputStreamReader的子类,而InputStreamReader包装了一个InputStream(Adapter design pattern),可以说FileReader就是一个编码语言翻译家,首先FileReader默认地认为InputStream是某种编码语言写成的,然后把它翻译成内部的语言(unicode),注意jvm世界的非常和谐内部都用unicode交流,所以我们看到了进过翻译家的帮忙,FileReader fr 输出的结果为6211,就是“我”的unicode。
那么FileReader貌似有个不好的毛病,它太自信了,它把InputStream就认为是某种语言(用getEncoding()可以查看到),当然这里它自信的没有问题,应为getEncoding返回的结果是gbk,也就是它把InputStream的字节当gbk来解析翻译去得到内部的unicode,显然我的windows下面的txt用的就是gbk(FileInputStream fis 输出的ced2也说明了这一点),所以我们的FileReader蒙对啦,哈哈。

当然,InputStreamReader 作为 FileReader的父类就严谨的多了(老一辈毕竟是过来人),在它的构造函数中你可以提供charset,来告诉Reader InputStream用的是什么编码(Reader应该怎么去读,把InputStream当什么来读),它的工作流程是这样,它内部有一个InputStream和charset的成员,然后它就用charset的方式去理解InputStream,把它翻译成unicode。通俗点说,就是最后我们要把外文翻译成中文,InputStream就是外文,而charset就是告诉翻译者InputStream是哪国的话(英语?法语?),这样外文就可以翻译成中文了。

以上就这么多,大家理解了吗,有纰漏处欢迎指出,谢谢了。


你可能感兴趣的:(java,IO,编码,Inputstream,reader)