【Java8源码分析】IO包-InputStream、FileInputStream和BufferedInputStream总结
来源:互联网 发布:淘宝上传没生产许可证 编辑:程序博客网 时间:2024/05/22 13:27
转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72875258
Java的IO类型可分为两大类:
- 面向字符流:Reader & Writer
- 面向字节流:InputStream & OutputStream
本文主要从源码方面分析一下常用的面向字节流的输入流。
- InputStream:所有输入流的抽象父类,定义了常用输入函数
- FileInputStream:针对文件的输入流
- BufferedInputStream:带有缓冲区的高效输入流
1 InputStream源码解析
public abstract class InputStream implements Closeable { private static final int MAX_SKIP_BUFFER_SIZE = 2048; // 读取下一个字节,返回0-255,读取失败返回-1,read()会阻塞直至读取成功或结束 public abstract int read() throws IOException; // 把字节流读入到传入的字节数组 public int read(byte b[]) throws IOException { return read(b, 0, b.length); } // 把字节读到字节数组指定位置 public int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int c = read(); if (c == -1) { return -1; } b[off] = (byte)c; int i = 1; try { // 循环调用read,一个字节一个字节读,有可能效率非常低 for (; i < len ; i++) { c = read(); if (c == -1) { break; } b[off + i] = (byte)c; } } catch (IOException ee) { } return i; }}
InputStream默认的read(byte[])
方法是通过多次调用read()
函数一个字节一个字节读到字节数组中。对于文件读取这种,read()
函数都要进行一次磁盘IO,所以会导致性能低下。
2 FileInputStream源码解析
public class FileInputStream extends InputStream{ private native int read0() throws IOException; private native int readBytes(byte b[], int off, int len) throws IOException; public int read() throws IOException { return read0(); } public int read(byte b[]) throws IOException { return readBytes(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { return readBytes(b, off, len); }}
FileInputStream中的read()
和read(byte[])
方法都是navtice方法。
InputStream类实现的read
是即时读取的,即每一次读取都会是一次磁盘IO操作(哪怕只读取了1个字节的数据),可想而知,如果数据量巨大,这样的磁盘消耗非常可怕。
InputStream类的read(byte[])
方法则是一次读取多个字节到buffer中。
3 BufferedInputStream源码解析
3.1 属性域
public class BufferedInputStream extends FilterInputStream { // 存储的输入流对象 protected volatile InputStream in; // 缓冲区大小默认未8MB private static int DEFAULT_BUFFER_SIZE = 8192; private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; // 缓冲区 protected volatile byte buf[]; // 缓冲区中有效数据容量 protected int count; // 缓冲区读到的当前位置 protected int pos; // 构造函数,默认缓冲区大小 public BufferedInputStream(InputStream in) { this(in, DEFAULT_BUFFER_SIZE); } // 构造函数,设置缓冲区大小 public BufferedInputStream(InputStream in, int size) { super(in); if (size <= 0) { throw new IllegalArgumentException("Buffer size <= 0"); } buf = new byte[size]; } }
3.2 read()函数
public synchronized int read() throws IOException { // 如果缓冲区已经读完,则调用fill填充缓冲区 if (pos >= count) { fill(); if (pos >= count) return -1; } return getBufIfOpen()[pos++] & 0xff;}//填充字节到缓冲区中,假设缓冲区中的数据已经全部读完private void fill() throws IOException { byte[] buffer = getBufIfOpen(); // ... // 前面省略了缓冲区扩容、缓冲区mark标记处理等代码 count = pos; // 一次性读取多个字节到缓冲区中 int n = getInIfOpen().read(buffer, pos, buffer.length - pos); if (n > 0) count = n + pos;}
BufferedInputStream改进了read()
方法,它会先从自身的缓冲区中取字节,当缓冲区的字节取完后,会调用fill()
函数把缓冲取一次性填充满,再取字节。
4 总结
(1)不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。
(2)带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多。
(3)有一种情况下,FileInputStream和BufferedInputStream的效率相差不大:即每次读取数据量接近或远超BufferedInputStream的缓冲区大小时(默认8MB),两者效率就没有明显差别了。
转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72875258
- 【Java8源码分析】IO包-InputStream、FileInputStream和BufferedInputStream总结
- 【Java8源码分析】IO包-Reader、BufferedReader和Scanner总结
- javaIO(2):InputStream和FileInputStream源码分析
- Java IO:FileInputStream和FileOutputStream使用详解及源码分析
- Java IO 系列源码分析——InputStream和OutputStream
- java I/O InputStream 及子类 FileInputStream 源码分析
- InputStream和FileInputStream
- inputStream 和FileInputStream 转换
- Java IO 之 FileInputStream & FileOutputStream源码分析
- java IO流分析:ByteArrayInputstream 和 BufferedInputStream
- BufferedInputStream与FileInputStream的IO效率对比
- IO<字节流>FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream
- IO流之FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream
- java基础——bufferedinputstream FileInputStream inputstream的比较
- Java InputStream&FileInputStream 源代码分析
- 总结 FileInputStream 与 FileOutputStream. BufferedInputStream 与 BufferedOutputStream
- Java IO:BufferedInputStream使用详解及源码分析
- Java中的InputStream和FileInputStream
- HTML5的10款经典游戏
- javascript正则表达式
- 有些地方需要注意的
- 《彻底理解》虚拟机三种网络模式
- bzoj4802 欧拉函数
- 【Java8源码分析】IO包-InputStream、FileInputStream和BufferedInputStream总结
- jQuery获取循环中的选中单选按钮radio的值
- Nginx配置报错unknown directive "echo"的解决
- configure: error: in `/inst/postgresql-9.5.2': configure: error: no acceptab
- spring框架实现步骤
- 用Nodejs连接MySQL
- if..else使用陷阱
- iOS项目运行注意事项
- java EE的三层结构:web层、service层、dao层