java IO小记

java IO 类学习

java处理IO的类如下所示:

虽然书中对每个类都有解释,但是看完之后都很难记住这些到底都是做什么的,在这里就具体分析一下每个类究竟都做了什么。

一个简单的标准输入

下面是一段最基本的java输入处理代码,可以看到一共涉及了三个类,InputStream、InputStreamReader 和BufferedReader。

    public static void main(String args[]) throws IOException
    {
        InputStream is = System.in;
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader bf = new BufferedReader(isr);
        System.out.println(bf.readLine());

    }

贴一段网上关于三个类的解释:

  • InputStream : 是所有字节输入流的超类,一般使用它的子类:FileInputStream等,它能输出字节流;
  • InputStreamReader : 是字节流与字符流之间的桥梁,能将字节流输出为字符流,并且能为字节流指定字符集,可输出一个个的字符;
  • BufferedReader : 提供通用的缓冲方式文本读取,readLine读取一个文本行, 从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。

看完了似懂非懂,接下来通过一个例子具体分析一下,分析过程中输入为“我说”两个字,控制台编码方式为utf-8,通过ultraedit查看可知,“我说”两个字utf-8编码对应的16进制为E6 88 91 E8 AF B4

InputStream

首先看一下InputStream,执行如下代码

InputStream is = System.in;
        int b;
        while ((b = is.read()) != 10){//10 对应0A,就是回车
            System.out.print(Integer.toHexString(b)+" ");

        }

输出结果为 e6 88 91 e8 af b4,这比较好理解,InputStream是字节流,而javaIO每次处理一个字节,输出内容与输入内容一致

InputStreamReader

接下来看一下InputStreamReader ,执行如下代码

InputStream is = System.in;
int b;
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
while ((b = isr.read()) != 10){
    System.out.print(Integer.toHexString(b)+" ");

}

输出结果为6211 8bf4,两个十六进制数为“我说”的unicode编码,所以可见所谓是字节流与字符流之间的桥梁就是按给定的编码方式,解码为unicode。

执行如下代码

InputStream is = System.in;
int b;
InputStreamReader isr = new InputStreamReader(is,"GBK");
while ((b = isr.read()) != 10){
    System.out.print(Integer.toHexString(b)+" ");

}

输出结果为93b4 6223 e1e9,这是为什么呢?因为如果按GBK解码,E6 88 91 E8 AF B4将会被解码为三个字符“鎴戣” 这三个字符的unicode编码为93b4 6223 e1e9。所以简单理解InputStreamReader主要的工作就是进行编码转换,即所谓的字节流转换为字符流。

BufferedReader

BufferedReader其实和InputStreamReader没有太大区别,唯一的区别在于InputStreamReader只能按单个字进行read,而BufferedReader通过缓存实现按行读取。

总结

总结来说,java的io操作最底层只能按字节方式进行操作,所以无论是读取文件、标准输入输出还是字符串等,最开始都需要创建对应的InputStream的子类对象(如果写文件就是OutputStream),可以直接调用对应的read或者write方法,但是只能按单个字节进行操作;如果需要一次操作多个字节,需要在InputStream基础上再创建BufferedInputStream对象;如果需要按字符进行操作就需要创建InputStreamReader 对象,进行解码;如果需要对多个字符进行操作;就需要在InputStreamReader的基础上在创建BufferedReader对象,于是就有了new BufferedReader(new InputStreamReader(new FileInputStream("filename")))的写法。而其他的诸如StringReader、FileReader就是几个基础类的组合而已。 Scanner类实现了字节流转换为字符流的功能和缓存的功能,同时还实现了hasNext等方法,可以更好的进行输入操作。