【Java基础】Java输入输出流(1)InputStream总结

    FileInputStream、ByteArrayInputStream这些从字面意思就比较好理解了,但是像BufferedInpitStream、DataInputStream这种包装流理解起来就不太容易了,经常看到的代码是下面这样的,一个套着一个,看起来很头大。

FileInputStream fileInputStream = new FileInputStream("test.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);

    这里就主要关注一下基础流和包装流使用上的区别,以及包装流存在的意义是什么。

    先看一下InputStrem里的基础流(FileInputStream…),如下图(待完善):
InputStream

    基础流也称为节点流,直接和要操作的对象进行绑定。以FileInputStream为例,其使用方式如下,结合代码理解:代表is这个输入流和./test.java文件绑定。

InputStream is = new FileInputStream("./test.java");

    通过基础流我们就基本上就可以完成输入输出的基本功能了,基本使用方法如下:

public static void main(String[] args) {
    try{
        InputStream inputStream = new FileInputStream("./test.java");
        //ByteArrayInputStream简单使用,其他的基础流使用方法类似
        //byte[] byteArr = new byte[10];
        //InputStream inputStream = new ByteArrayInputStream(byteArr);
        byte[] byteBuf = new byte[10];
        int num = 0;
        while ( (num = inputStream.read(byteBuf)) > 0) {
            System.out.print(new String(byteBuf, 0 , num));
        }
    }catch (IOException iex) {
        System.out.print("读取数据流发生错误");
    }
}

    那么疑问来了,既然基础流已经可以完成输入输出功能了,为什么还要有那么多的包装流。

    我们的要求总是苛刻的,基本功能是完成了, 就多了一些附加的要求。那么如何在不改变基础流类实现代码的前提下,对其添加一些功能呢?这时各种包装流就出现了,有为了提高读取效率出现的BufferedInputStream,有为了适应不同类型的数据(int,double等)的读取的DataInputStream,有为了实现数据的重复读取出现的PushbackInputStream。

    需要说明的是,基础功能还是由基础流来完成,包装流是用来提供附加功能的,基础流和包装流要结合起来才能完成一个功能更强大的输入输出流。

    先看一下以下包装流:
包装流
    除此之外,还有DataInputStream、ObjectInputStream等,这些待之后完善后贴出来。

    现在实现附加功能的包装流有了,那么怎么使用呢?接下来先以BufferedInputStream为例说明一下包装流的用法:

public static void main(String[] args) {
    try{
        FileInputStream fileInputStream = new FileInputStream("test.txt");
        //将fileInputStream这个基础流包装成BufferedInputStream
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        byte[] byteArr = new byte[10];
        int num = 0;
        while( (num = bufferedInputStream.read(byteArr)) > 0 ) {
            System.out.print(new String(byteArr , 0 , num));
        }
    }catch (IOException iex) {
        System.out.print("读取数据流发生错误");
    }
}

    从BufferedInputStream的使用方式上来说,我们似乎看不出来这个包装流提供了什么优于基础流的功能。要明确这一点,就要从BufferedInputStream的实现来说了,BufferedInputStream类的实现中包含了一个数组buf用来缓存数据,这个数组的默认大小是8192。在程序调用read方法读取数据的时候,会判断缓存数组buf中剩余的数据是否足够(取数据的时候,会传人一个byte数组,输入流数据足够的情况下会填满这个数组),足够的时候,会从这个buf中取出数据拷贝到byte中;不够的话会调用BufferedInputStream的fill()方法来将buf填充满,然后再从这个buf中取出数据填充byte数组。因为buf的大小一般来说是大于byte数组的大小的(除非你定义的byte数组的大小超过8192,当然BufferedInputStream也提供了一个构造函数供用户在实例化的时候自行定义buf数组的大小),所以在程序取数据的时候大多数情况下直接从buf数组中取就可以了。用具体的数字来说:假设我们的byte数组的大小是1024,buf数组的大小是8192,那么使用BuferedInputStream时,读取8192个字节需要与外设交互的次数为1,而不使用的情况下需要交互8次,这就是BufferefInputStream提高效率的原理了。减少了程序和硬盘等外设的交互(于外设的交互所需的时间远远大于于内存交互的时间),从而也就提高了读取数据的效率。

以上整理不全面,后续会慢慢补充完善
如有不当之处,欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值