BufferedInputStream为带缓存的输入流,BufferedOutputStream为带缓存的输出流。缓存输入输出就是在读写磁盘文件之前,先把数据读取或写入到预先分配的内存区域(这片内存区域称为缓冲区),当缓冲区存储的数据已满时,再进行磁盘文件的读写操作。通过缓冲区读写文件带来的好处是可以优化程序的输入输出性能,提供程序读写磁盘文件的速度。
BufferedInputStream类的工作依赖于InputStream,它需要使用InputStream类进行磁盘文件的读写。BufferedInputStream读取文件的工作原理如下图所示:
BufferedInputStream读取文件的工作原理
BufferedInputStream类在内部维护一个缓冲区。实例化BufferedInputStream对象时,需要传入InputStream的实例化对象,当程序调用BufferedInputStream对象从文件读取数据时,它会先判断缓冲区是否有读取的文件数据,如果有就从缓冲区读取,否则就调用InputStream对象从文件读取数据填满缓冲区。
BufferedOutputStream类和BufferedInputStream类的工作原理是相同的,只不过一个是写入文件数据,一个是读取文件数据。BufferedOutputStream类在内部也维护一个缓冲区,当程序调用BufferedOutputStream将数据写入文件时,它会先把数据写入缓冲区,当缓冲区已满时,再调用OutputStream将缓冲区的数据写入到文件。BufferedOutputStream类也提供了flush()方法,可以强制将缓冲区的数据写入到文件。
1、BufferedInputStream类
BufferedInputStream类有默认的缓冲区空间,程序可以在类的构造函数中传入需要的缓冲区空间大小。
BufferedInputStream类的构造函数如下:
● public BufferedInputStream(InputStream in);
该构造函数创建具有默认缓冲区空间的输入流。
● public BufferedInputStream(InputStream in, int size);
该构造函数创建指定缓冲区空间大小的输入流。
InputStream类是BufferedInputStream的父类,因此InputStream类定义的方法,BufferedInputStream都可以使用。
案例1:建立BufferedInputStreamTest测试类,读取图片文件。
在PCoreUnit6项目新建buffer包,在buffer包下新建BufferedInputStreamTest类。代码如下:
package buffer;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @ClassName: BufferedInputStreamTest
* @Description: 输入与输出(缓存输入输出流)案例1
* @author 编程训练营
* @date
*
*/
public class BufferedInputStreamTest {
/**
* @Title: main
* @Description: Java程序入口main方法
* @param @param args 参数
*
* @return void 返回类型 @throws
*/
public static void main(String[] args) {
// 读取的图片文件路径
String filename = "d:\\001.png";
BufferedInputStream bufferedInput = null;
// 申请读取文件的缓冲区
byte[] buffer = new byte[1024];
try {
// 创建BufferedInputStream 对象
bufferedInput = new BufferedInputStream(new FileInputStream(filename));
int bytesRead = 0;
// 从文件中按字节读取内容,到文件尾部时read方法将返回-1
while ((bytesRead = bufferedInput.read(buffer)) != -1) {
// 将读取的字节转为字符串对象
String content = new String(buffer, 0, bytesRead);
System.out.print(content);
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
// 关闭 BufferedInputStream
try {
if (bufferedInput != null)
bufferedInput.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}案例代码完成读取图片文件的操作,使用BufferedInputStream类的read方法将图片文件数据读入到buffer缓冲区,并将buffer缓冲区的输出到控制台。因为读取的图片文件是二进制文件,所以在控制台显示的是乱码。关闭文件放到了finally语句块,这样做的好处是不管是否发生文件读取异常,都会关闭已打开的文件资源。
程序执行结果如下图所示:

2、BufferedOutputStream类
BufferedOutputStream类有默认的缓冲区空间,程序可以在类的构造函数中传入需要的缓冲区空间大小。BufferedOutputStream类的构造函数如下:
● public BufferedOutputStream(OutputStream out);
该构造函数创建具有默认缓冲区空间的输出流。
● BufferedOutputStream(OutputStream out, int size);
该构造函数创建指定缓冲区空间大小的输出流。
OutputStream类是BufferedOutputStream的父类,因此OutputStream类定义的方法,BufferedOutputStream都可以使用。
案例2:建立BufferedOutputStreamTest测试类,建立一个二进制文件,输出数据到新建的二进制文件。
在buffer包下新建BufferedOutputStreamTest类。代码如下:
package buffer;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @ClassName: BufferedOutputStreamTest
* @Description: 输入与输出(缓存输入输出流)案例2
* @author 编程训练营
* @date
*
*/
public class BufferedOutputStreamTest {
/**
* @Title: main
* @Description: Java程序入口main方法
* @param @param args 参数
* @return void 返回类型
* @throws
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
BufferedOutputStream bufferoutput = null;
//写数据
try {
bufferoutput = new BufferedOutputStream(new FileOutputStream("d:\\outtest.dat")) ;
// 将String对象的内容转换为字节数组,并写入文件
bufferoutput.write("这是一个二进制文件".getBytes());
System.out.println("文件创建成功");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("文件创建失败");
e.printStackTrace();
} finally {
//释放资源
try {
bufferoutput.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}案例代码创建一个二进制文件,并写入字符串对象的内容。虽然创建的是二进制文件,但使用记事本仍然可以看到写入的中文内容,因为新建的二进制文件存储的是中文内容的文字编码。