一、概述
字节流与字符流:属于IO流的入门,那么即将学习的是更大的流
缓冲流:高效流,是在基本流对象的基础上创建而来的,就像普通人穿上铠甲一样,相当于对基本流的一种增强,就是对四个基本的FileXXX流的增强,所以缓冲流也分为四个流。
二、分类
按照类型来区分
字节缓冲流:BufferedInputStream、BufferOutputStream
字符缓冲流:BufferedReader、BufferedWriter
缓冲流的基本原理,是在创建流对象的时候,会创建一个内置的默认小的缓冲区数组,通过缓冲区进行续写,减少系统IO的次数,提高读写效率
三、缓冲流的使用
1.字节缓冲流
为了更明了的体现缓冲流的优势,我们用分别用【普通流】和【缓冲流】进行续写对比
需求:将一个视频文件复制到指定路径(也可以用一个比较大点的文件,这里这个视频文件7MB)
构造方法:
- public BufferedInputStream(InputStream in):创建一个 新的缓冲输入流
- public BufferedOutputStream(OutputStream out):创建一个 新的缓冲输出流
代码演示:
public class Test {
public static String path = "day13_Properties类&缓冲流&转换流&序列化流&装饰着模式&commons-io工具包\\resources\\x.mp4";
public static String path_copy = "day13_Properties类&缓冲流&转换流&序列化流&装饰着模式&commons-io工具包\\resources\\x_copy.mp4";
public static void main (String[] args) throws IOException {
method01();
method02();
method03();
method04();
}
// 使用字节进行续写 普通续写 38s
private static void method01 () throws IOException {
// 1.创建字节缓冲流对象
FileInputStream fis = new FileInputStream(path);
//BufferedInputStream bfis = new BufferedInputStream(fis);
// 2.创建字节缓冲输出对象,关联
FileOutputStream fos = new FileOutputStream(path_copy);
//BufferedOutputStream bfos = new BufferedOutputStream(fos);
// 普通流拷贝视频软件
// 1.获取当前系统时间
long start = System.currentTimeMillis();
// 2.定义一个int类型的变量,存储读取到的字节数据
int len;
// 3.循环读取数据
while ((len = fis.read()) != -1){
fos.write(len);
}
// 4.关闭流
fos.close();
fis.close();
// 5.获取当前系统时间
long over = System.currentTimeMillis();
System.out.println("共用时" + (over - start));
}
// 使用字节进行续写 缓冲流 92ms
private static void method02 () throws IOException {
// 1.创建字节缓冲流对象
FileInputStream fis = new FileInputStream(path);
BufferedInputStream bfis = new BufferedInputStream(fis);
// 2.创建字节缓冲输出对象,关联
FileOutputStream fos = new FileOutputStream(path_copy);
BufferedOutputStream bfos = new BufferedOutputStream(fos);
// 普通流拷贝视频软件
// 1.获取当前系统时间
long start = System.currentTimeMillis();
// 2.定义一个int类型的变量,存储读取到的字节数据
int len;
// 3.循环读取数据
while ((len = bfis.read()) != -1){
bfos.write(len);
}
// 4.关闭流
bfos.close();
bfis.close();
// 5.获取当前系统时间
long over = System.currentTimeMillis();
System.out.println(over - start);
}
// 使用数组进行续写 缓冲流 16ms
private static void method03 () throws IOException {
// 1.创建字节缓冲流对象
FileInputStream fis = new FileInputStream(path);
//BufferedInputStream bfis = new BufferedInputStream(fis);
// 2.创建字节缓冲输出对象,关联
FileOutputStream fos = new FileOutputStream(path_copy);
//BufferedOutputStream bfos = new BufferedOutputStream(fos);
// 1.获取当前系统时间
long start = System.currentTimeMillis();
// 2.定义一个int类型的变量,存储读取到的字节数据
int len;
byte[] bytes = new byte[8192];
// 3.循环读取数据
while ((len = fis.read(bytes)) != -1){
fos.write(len);
}
// 4.关闭流
fos.close();
fis.close();
// 5.获取当前系统时间
long over = System.currentTimeMillis();
System.out.println(over - start);
}
// 使用数组进行续写 缓冲流 16ms
private static void method04 () throws IOException {
// 1.创建字节缓冲流对象
FileInputStream fis = new FileInputStream(path);
BufferedInputStream bfis = new BufferedInputStream(fis);
// 2.创建字节缓冲输出对象,关联
FileOutputStream fos = new FileOutputStream(path_copy);
BufferedOutputStream bfos = new BufferedOutputStream(fos);
// 1.获取当前系统时间
long start = System.currentTimeMillis();
// 2.定义一个int类型的变量,存储读取到的字节数据
int len;
byte[] bytes = new byte[8192];
// 3.循环读取数据
while ((len = bfis.read(bytes)) != -1){
bfos.write(len);
}
// 4.关闭流
bfos.close();
bfis.close();
// 5.获取当前系统时间
long over = System.currentTimeMillis();
System.out.println(over - start);
}
}
输出结果:
共用时39609
共用时47
共用时16
共用时16
明显可以看出,【普通流】需要用时39609毫秒,【缓冲流】只需要用47毫秒,数组的话没什么区别,不相伯仲,所以,日常需要进行文件传输还是用数组效率比较高点。
2.字符缓冲流
构造方法:
- public BufferedReader(Reader in):创建一个 新的缓冲输入流
- public BufferedWriter(Writer out):创建一个 新的缓冲输出流
特有方法:
- BufferedReader:public String readLine():读一行文字,如果已到了流的末尾,返回null
- BufferedReader:public void newLine():写一行 行分隔符,由系统属性定义符号
代码演示:
需求:需要将向指定路径文件写入一首诗,然后再将指定路径文件的内容读出来
public class Test {
public static String path = "day13_Properties类&缓冲流&转换流&序列化流&装饰着模式&commons-io工具包\\resources\\a.txt";
public static void main (String[] args) throws IOException {
FileWriter fw = new FileWriter(path);
BufferedWriter bfw = new BufferedWriter(fw);
// 写数据
bfw.write("鹅鹅鹅");
bfw.newLine();
bfw.write("白毛浮绿水,");
bfw.newLine();
bfw.write("曲项向天歌。");
bfw.newLine();
bfw.write("红掌拨清波,");
bfw.newLine();
bfw.write("骆宾王的咏鹅");
bfw.newLine();
bfw.close();
method01();
}
private static void method01() throws IOException {
// 创建字符缓冲流对象
FileReader fr = new FileReader(path);
BufferedReader bfr = new BufferedReader(fr);
// 定义一个String变量,用来存储读到的行数据
String line;
// 循环读取数据
while( (line = bfr.readLine()) != null){
System.out.println(line);
}
// 关闭流
bfr.close();
}
}
输出结果:
鹅鹅鹅
白毛浮绿水,
曲项向天歌。
红掌拨清波,
骆宾王的咏鹅
四、文本排序练习
需求:现有如图的文本文档,需要将它们按序号重新排列
代码演示:
public class Test {
public static String path = "day13_Properties类&缓冲流&转换流&序列化流&装饰着模式&commons-io工具包\\resources\\c.txt";
public static void main (String[] args) throws IOException {
/*
* 需求:请将文本恢复顺序
* */
// 1.创建字符缓冲流对象
FileReader fr = new FileReader(path);
BufferedReader bfr = new BufferedReader(fr);
// 2.定义一个集合用来存储文本
List<String> list = new ArrayList<>();
String txt;
while ((txt = bfr.readLine()) != null){
list.add(txt);
}
Collections.sort(list);
FileWriter fw = new FileWriter(path);
BufferedWriter bfw = new BufferedWriter(fw);
for (String str : list) {
System.out.println(str);
bfw.write(str);
bfw.newLine();
}
// 3.关闭流
bfr.close();
bfw.close();
}
}
排序后: