- 能够使用字节缓冲流读取数据到程序
- 能够使用字节缓冲流写出数据到文件
能够高效读写的缓冲流,,能够转换编码的转换流,能够持久化存储对象的序列化流等等。这些功能更为强大的流,都是在基本的流对象基础之上创建而来的,就像穿上铠甲的武士一样,相当于是对基本流对象的一种增强。
1. 缓冲流
能够高效读写的缓冲流,也叫高效流,继承了OutputStream、InputStream,是对4个基本的FileXxx
流的增强,所以也是4个流,按照数据类型分类:
- 字节缓冲流:
BufferedInputStream
,BufferedOutputStream
缓冲流的基本原理
是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
2. 构造方法
public BufferedInputStream(InputStream in)
:创建一个 新的缓冲输入流。public BufferedInputStream(InputStream in ,int size)
:创建一个 新的缓冲输入流,指定缓冲流内部缓冲区的大小。public BufferedOutputStream(OutputStream out)
: 创建一个新的缓冲输出流。public BufferedOutputStream(OutputStream out, int size)
: 创建一个新的缓冲输出流,指定缓冲流内部缓冲区的大小。
参数
OutputStream out
:字节输出流- 我们可以传递
FileOutputStream
,缓冲流会给FileOutputStream
增加一个缓冲区,提高FileOutputStream
的写入效率 int size
:指定缓冲流内部缓冲区的大小,不指定默认
代码如下:
// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
3. 使用步骤【重点】
字节缓冲输出流
-
创建
FileOutputStream
对象,构造方法中绑定要输出的目的地 -
创建
BufferedOutputStream
对象,构造方法中传递FileOutputStream
对象对象,提高FileOutputStream
对象效率 -
使用
BufferedOutputStream
对象中的方法write,把数据写入到内部缓冲区中 -
使用
BufferedOutputStream
对象中的方法flush,把内部缓冲区中的数据,刷新到文件中 -
释放资源(会先调用flush方法刷新数据,第4部可以省略)
演示代码:
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo01BufferedOutputStream {
public static void main(String[] args) throws IOException {
//1.
FileOutputStream fos = new FileOutputStream("E:\\i.txt");
//2.FileOutputStream对象效率
BufferedOutputStream bos = new BufferedOutputStream(fos);
//3.
bos.write("我把数据写入到内部缓冲区中".getBytes());
//4.
bos.flush();
//5.
bos.close();
}
}
字符缓冲输出流
- 创建
FileInputStream
对象,构造方法中绑定要读取的数据源 - 创建
BufferedInputStream
对象,构造方法中传递FileInputStream
对象,提高FileInputStream
对象的读取效率 - 使用
BufferedInputStream
对象中的方法read,读取文件 - 释放资源
演示代码:
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class Demo02BufferedInputStream {
public static void main(String[] args) throws IOException {
//1
FileInputStream fis = new FileInputStream("E:\\i.txt");
//2
BufferedInputStream bis = new BufferedInputStream(fis);
//3
//int read()从输入流中读取数据的下一个字节。
/*int len = 0;//记录每次读取到的字节
while((len = bis.read())!=-1){
System.out.println(len);
}*/
//int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
byte[] bytes =new byte[1024];//存储每次读取的数据
int len = 0; //记录每次读取的有效字节个数
while((len = bis.read(bytes))!=-1){
// System.out.println(len); // 3
// String(char[] value) 把字符数组转换为字符串
System.out.println(new String(bytes,0,len)); // abc
}
//4.
bis.close(); // 关闭缓冲流后,字节流自动关闭
}
}
4. 效率测试
查询API,缓冲流读写方法与基本的流是一致的,我们通过复制大文件(375MB),测试它的效率。
代码如下:
- 基本流
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
文件复制的步骤
1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
3.使用字节输入流对象中的方法read读取文件
4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
5.释放资源(先关写的,后关闭读的;如果写完了,肯定读取完毕了)
*/
public class Demo01CopyFile {
public static void main(String[] args) throws IOException {
long s = System.currentTimeMillis();
//1
FileInputStream fis = new FileInputStream("E:\\tu.jpg");
//2
FileOutputStream fos = new FileOutputStream("E:\\pic\\tu1.jpg");
//一次读取一个字节写入一个字节的方式
/*//3
int len = 0;
while((len = fis.read())!=-1){
//4
fos.write(len);
}*/
//使用数组缓冲读取多个字节,写入多个字节
byte[] bytes = new byte[1024];
//3.使用字节输入流对象中的方法read读取文件
int len = 0;//每次读取的有效字节个数
while((len = fis.read(bytes))!=-1){
//4
fos.write(bytes,0,len);
}
//5
fos.close();
fis.close();
long e = System.currentTimeMillis();
System.out.println("复制文件共耗时:"+(e-s)+"毫秒"); // 3533 | 6
}
}
- 缓冲流
import java.io.*;
/*
文件复制练习:一读一写
明确:
数据源: c:\\1.jpg
数据的目的地: d:\\1.jpg
文件复制的步骤:
1.创建字节缓冲输入流对象,构造方法中传递字节输入流
2.创建字节缓冲输出流对象,构造方法中传递字节输出流
3.使用字节缓冲输入流对象中的方法read,读取文件
4.使用字节缓冲输出流中的方法write,把读取的数据写入到内部缓冲区中
5.释放资源(会先把缓冲区中的数据,刷新到文件中)
*/
public class Demo02CopyFile {
public static void main(String[] args) throws IOException {
long s = System.currentTimeMillis();
//1
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\tu.jpg"));
//2
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\pic\\tu3.jpg"));
//3
//一次读取一个字节写入一个字节的方式
int len = 0;
while((len = bis.read())!=-1){
bos.write(len);
}
// 5
bos.close();
bis.close();
long e = System.currentTimeMillis();
System.out.println("复制文件共耗时:"+(e-s)+"毫秒"); // 33 | 5
}
}
如何更快呢?使用数组的方式
代码如下:
public class BufferedDemo {
public static void main(String[] args) throws FileNotFoundException {
// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\tu.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\pic\\tu3.jpg"));
// 读写数据
int len;
//使用数组缓冲读取多个字节,写入多个字节
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0 , len);
}
// 5
bos.close();
bis.close();
// 记录结束时间
long e = System.currentTimeMillis();
System.out.println("复制文件共耗时:"+(e-s)+"毫秒"); // 33 | 5
}
}
缓冲流使用数组复制时间:5毫秒