`
fj_ding
  • 浏览: 37324 次
社区版块
存档分类
最新评论

BufferedOutputStream的缓存功能解析(源码阅读)

阅读更多
要介绍BufferedOutputStream,我们先了解一下OutputStream类
抽象类OutputStream类有三个write方法


  1. public abstract void write(int b)
  2. public void write(byte b[])
  3. public void write(byte b[], int off, int len)

由上面我们可以看出第一个write方法是让子类覆盖的,而第二个人write(byte b[])方法源代码如下
public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }

所以可见最后处理还是调用第三个方法write(byte b[],int off,int len),该方法源码如下:

public void write(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if ((off 0) || (off > b.length) || (len 0) ||
                   ((off + len) > b.length) || ((off + len) 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        for (int i = 0 ; i //注意这儿,这儿其实调用前面的抽象方法write(int b),同时还发生了自动转型
            write(b[off + i]);
        }
    }

问题
我们先不看抽象方法是如何实现的,也就是说OutputStream也具有缓存器功能,我们可以将要写入到流中的数据写到一个byte[] buf数组中,然后调用write(byte b[])或者write(byte b[], int off, int len)也可以,那为什么还要BufferedInputStream类干什么呢,他们有什么区别呢。同时我们知道BufferedInputStream类中还有一个flush()方法,在OutputStream流中没有flush()方法,这又是为什么呢?flush()是不是必须的呢,接下来看一下BufferedOutputStream类;
首先,BufferedOutput将OutputStream类对象作为一个构造方法的参数的。
首先看一下BufferedOutputStream 类源代码


public
class BufferedOutputStream extends FilterOutputStream {

    //这儿定义了一个byte[]数组,用来充当缓存器  
    protected byte buf[]; 
    //这个变量是重点,他就是用来记录当前缓存器中的字节数量的
    protected int count; 
    //我们初始化创建一个对象的时候给了这个buf这个数组8192个字节.
    public BufferedOutputStream(OutputStream out) {
        this(out, 8192);
    }

    public BufferedOutputStream(OutputStream out, int size) {
        super(out);
        if (size 0) {
            throw new IllegalArgumentException("Buffer size );
        }
      // 这儿创建一个给定大小的数组对象来充当缓存器
        buf = new byte[size];
    }

    public synchronized void write(int b) throws IOException {
        if (count >= buf.length) {
            flushBuffer();
        }
        buf[count++] = (byte)b;
    }

//该方法是重点    
public synchronized void write(byte b[], int off, int len) throws IOException {
        //如果传进来的数组长度大于buf 数组的长度,则直接调用OutputStream对象的write方法。
        if (len >= buf.length) {

            flushBuffer();
            out.write(b, off, len);
            return;
        }
        //验证BufferedOutputStream 类中buf剩下的空间能否装得下传进来的数组。如果不能则先将当前buf数组中数据写入底层io流中
        if (len > buf.length - count) {
            flushBuffer();
        }
        //该处是重点,如果在当前BufferedOutputStream 类中buf数组没有满,则将传进来的数组复制到当前类对象buf数组中,同时更新count的值。
        System.arraycopy(b, off, buf, count, len);
        count += len;
   //调用flushBuffer方法也就是将不满8192个字节数组中的数据发送出去。同时将count置零。
    private void flushBuffer() throws IOException {
        if (count > 0) {
            out.write(buf, 0, count);
            count = 0;
        }
    }

    //强制将buf数据中未满8192个字节的数据写入底层io中。
    public synchronized void flush() throws IOException {
        flushBuffer();
        out.flush();
    }
}


结论:
OutputStream的缓存器(数组)与BufferedOutputStream中类的缓存器(数组)本质是一样的,只是BufferedOutputStream类中将要写入到底层io流中的数据先凑个整,然后再一起写入底层io流中,这样就大大节省了io操作,大大提高了io利用率,写一次io是很费资源的。这样也出现了一个问题,假设向硬盘中写入一个文件,文件最后数据比默认值8192个字节小,则BufferOutputStream就不会将这些数据写入底层io流中,造成文件缺失,因此就需要在close()前调用flush()方法,强制将还没有装满buf数组的数据写入底层io中。同时也可以看出节点流是不用flush()方法的,而一般的处理流都会采用固定buf这种方式的,比如常用的PrintWriter里面其实操作的就是一个BufferedWriter对象,因此也需要调用flush()方法来刷新,因为默认是不刷新的。

参考:

http://www.bdqn.cn/news/201311/12111.shtml
分享到:
评论

相关推荐

    BufferedOutputStream 介绍_动力节点Java学院整理

    BufferedOutputStream 是缓冲输出流。它继承于FilterOutputStream。 BufferedOutputStream 的作用是为另一个输出流提供“缓冲功能”。

    BufferedOutputStream的用法---马克-to-win java视频

    BufferedOutputStream的用法---马克-to-win java视频 缓存输出流

    BufferedOutputStream.html

    java的BufferedOutputStream,开发过程中使用字符流,效率提高。字符流很好,初学者要分清字符流和字节流

    疯狂Java flashget源码

    《疯狂Java flashget源码解析》 在编程领域,源码是理解软件工作原理的最直接途径。"疯狂Java flashget源码"提供了一个模仿知名下载工具FlashGet的多线程下载功能的Java实现,这对于Java开发者,尤其是对多线程编程...

    java下载程序源码

    ### Java下载程序源码解析与知识点详解 在探讨如何通过Java实现资源下载的功能时,我们首先需要理解几个关键概念:HTTP响应、文件流操作、以及MIME类型与内容编码。以下将从标题“java下载程序源码”和描述“一个...

    网络蚂蚁Java版源码下载

    - 字节流与字符流:在处理大文件时,可能会使用BufferedInputStream和BufferedOutputStream提高效率。 5. **进度条显示**: - 用户界面更新:网络蚂蚁通常有进度条显示下载进度,这涉及线程间通信,可能使用Swing...

    JavaWeb - Excel_Word(2003_2007、上传下载、解析生成、导入导出)源码

    这个源码包提供了对2003至2007版本的Excel和Word文档的支持,涵盖了文件的上传、下载、解析、生成以及导入导出功能。下面将详细阐述这些知识点。 1. **JavaWeb基础**: JavaWeb是基于Java技术构建的Web应用程序,...

    FilterOutputStream 源码分析

    在源码阅读过程中,我们需要注意FilterOutputStream如何通过`checkWrite()`方法来检查是否可以进行写入操作,以及如何通过`flushBuffer()`方法来刷新内部缓冲区(如果有的话)。这些细节对于理解流的工作机制至关...

    java版飞鸽传书源码,java版飞鸽传书源码

    3. **文件上传与下载**:源码中会实现文件的上传和下载功能。文件上传可能包括读取本地文件、将文件内容转化为字节流并发送到服务器;下载则涉及接收服务器发送的数据,写入本地文件。这部分可能会用到...

    Java版开源Winzip压缩工具源码

    在这个项目中,会用到FileInputStream、FileOutputStream等类来处理文件,以及BufferedInputStream、BufferedOutputStream提高读写效率。 2. **压缩与解压缩算法**:项目可能采用了ZipOutputStream和ZipInputStream...

    android文件读写源码

    本文将深入解析Android文件读写源码,探讨如何在Android应用中创建、读取、修改和删除文件,并涉及权限管理和存储位置的选择。 首先,Android提供了`java.io`和`java.nio`两个包来支持文件操作。在`java.io`包中,`...

    Java从网络取得文件Demo源码.zip

    在Java编程环境中,从网络获取文件是一项常见的任务,特别是在开发Web应用、下载更新或实现数据同步等场景。这个"Java从网络取得文件...通过阅读和分析这些源码,开发者可以加深对Java网络API的理解,提升开发能力。

    java版飞鸽传书源码

    《Java版飞鸽传书源码解析》 在IT领域,源码是程序员的语言,它揭示了软件运行的内在逻辑。对于Java开发者来说,能够接触到用Java编写的飞鸽传书源码实属罕见,因为通常这类应用多采用VB(Visual Basic)或其他更...

    Java版飞鸽传书文件传输源码.rar

    源码中可能会使用BufferedInputStream和BufferedOutputStream来提高读写效率,并通过DataInputStream和DataOutputStream进行数据结构的序列化和反序列化。 5. **用户界面**:虽然描述中没有提及,但通常一个完整的...

    飞鸽传书源码,使用java实现

    《深入解析Java版“飞鸽传书”源码》 在信息技术日新月异的今天,源码学习已经成为提升编程技能的重要途径。本篇将详细探讨一个基于Java实现的“飞鸽传书”项目的源码,它是一个网络通信工具,采用Swing库构建用户...

    javassm源码上传图片功能

    根据提供的文件信息,我们可以推断出本篇文章将围绕“javassm源码上传图片功能”的实现与使用展开讨论。此功能基于javassm框架(Java + Spring + SpringMVC + MyBatis)进行开发,并提供了二次开发的可能性。下面将...

    安卓Android源码——扫描手机中的图片,仿微信显示本地图片效果.rar

    因此,源码可能会采用像Picasso、Glide或Universal Image Loader这样的第三方库来实现图片的异步加载、缩放和缓存,从而优化性能和内存使用。 此外,考虑到用户体验,源码可能实现了图片的分页加载和无限滚动效果,...

    飞鸽传书java版源码

    《飞鸽传书Java版源码深度解析》 在信息技术高速发展的今天,各种通信软件层出不穷,其中“飞鸽传书”作为一款老牌的局域网通信工具,因其简单易用、传输快速的特点深受用户喜爱。本文将深入探讨使用Java语言编写的...

    java源码大全

    - **缓冲流**:BufferedInputStream和BufferedOutputStream增加了缓冲功能,提高数据读写的效率。 - **转换流**:InputStreamReader和OutputStreamWriter用于在字节流与字符流之间转换。 - **对象序列化与反序列...

    java源码:开源Winzip压缩工具Java版源码.rar

    【标题】:“java源码:开源Winzip压缩工具Java版源码.rar”指的是一个开源的Java实现的压缩工具,它的功能类似于知名的Winzip软件。这个压缩工具提供了在Java环境中对文件进行压缩和解压缩的能力,使得开发者能够在...

Global site tag (gtag.js) - Google Analytics