06JavaIO-6. FileInputStream和BufferedInputStream源码分析
  PQopDDLXkGHB 2023年11月02日 44 0


FileInputStream:针对文件的输入流
BufferedInputStream:带有缓冲区的高效输入流

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中。

BufferedInputStream源码解析

属性域

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];
}
}

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()函数把缓冲取一次性填充满,再取字节。

总结

(1)不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。
(2)带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多。
(3)有一种情况下,FileInputStream和BufferedInputStream的效率相差不大:即每次读取数据量接近或远超BufferedInputStream的缓冲区大小时(默认8MB),两者效率就没有明显差别了。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

上一篇: 【高等数学】定积分 下一篇: UML建模
  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  eo9lmrKcoG9P   2023年12月11日   17   0   0 组播多点HCIP数据
PQopDDLXkGHB