Java中FileInputStream与BufferedInputStream的区别

本文介绍了Java中的FileInputStream和BufferedInputStream。FileInputStream用于读取字节流,而BufferedInputStream通过内部缓冲区提高读取效率。示例代码展示了如何使用这两种流进行文件读取,强调了缓冲区在提高性能方面的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FileInputStream是InputStream的一个子类,是字节输入流,而InputStream是一个java标准库中提供的一个基本的输入流,位于java.io这个包里,需要注意的是,InputStream不是接口,而是一个抽象类,是所有输入流的超类。

下面的代码演示了如何完整的读取一个FileInputStream的所有字节:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class Demo01 {
	public static void main(String[] args) {
		// 定义
		InputStream in = null;
		
		
		try {
			// 创建(实例化)“字节输入流”对象
			in = new FileInputStream("D:\\test\\aa.txt");
			
			// 保存每次读取到的字节值
			int data = -1;
			
			// 正常读取 : 0-255
			// 读取末尾 : -1
			while((data = in.read()) != -1) {
				System.out.print((char)data);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
				in = null;
			}
		}
	}
}

那么一次读取一个字节效率过于慢,在FileInputStream类中提供了read()方法的重载形式:

    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 {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) {
        }
        return i;
    }

需要先定义一个byte数组作为缓冲区,read会读取尽可能多的字节并填充到byte[]数组,返回读取的字节数。

FileInputStream使用缓冲区一次读取多个字节代码如下:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class Demo03 {
	public static void main(String[] args) {
		try (InputStream in = new FileInputStream("D:\\test\\mkl.jpg")) {
			
			// 批量读取(缓冲)
			byte[] buff = new byte[1024];
			
			int len = -1;
			
			while((len = in.read(buff)) != -1) {
				System.out.printf("本次读取%d个字节:%s\n",len,Arrays.toString(buff));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

BufferedInputStream是带有缓冲区的字节输入流,继承于FileInputStream,本质上是通过一个内部缓冲区数组实现的,默认容量是8192,具体实现采用了装饰器模式,在构造方法中需要传入一个输入流对象,如果没有传入缓冲区容量,则使用默认的容量。从磁盘中一次读取相应容量的字节,存放到内存中的内部缓冲区。

在使用read()方法中读取字节时,FileInputStream是从磁盘中直接读取字节,而BufferedInputStream是从内存中的内部缓冲区读取字节,相比之下,从内存中读取比从磁盘中读取速度快,性能好。

jdk中BufferedInputStream类的部分源代码:

    private static int DEFAULT_BUFFER_SIZE = 8192;

    protected volatile byte buf[];

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

使用BufferedInputStream读取字节代码如下

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class Demo04 {
	public static void main(String[] args) {
		// 带有缓冲区的字节输入流
		// 缓冲区默认大小为8192
		try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\test\\mkl.jpg"))) {
			// 从内存的buf缓冲区中读取1个字节
			// bis.read()
			int data = -1;
			
			while((data = bis.read()) != -1) {
				System.out.println(data);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仙草不加料

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值