92-Java的缓冲流概述、体系、字节缓冲流使用
一、关于IO流我们还要学会什么?
1、缓冲流
- 我们之前学习的流都是属于基础流,性能其实不是最好的,缓冲流读取数据的性能会更好!
2、转换流
- 使用字符流读取中文不会乱码,原因是什么?
- 那么如果读取的文件编码与代码编码不一致怎么办?
3、序列化
- 如何把Java对象进行长久保存。
4、打印流
- 开发中有一种使用极为方便,性能高效的写数据的流,使用的很多。
5、IO框架等
- IO流原生的API使用起来其实挺麻烦的,有没有更好用的方式。
二、缓冲流
1、概述
- 缓冲流也称为高效流、或者高级流。之前学习的字节流可以称为原始流。
- 作用:缓冲流自带缓冲区,可以提高原始字节流、字符流读写数据的性能。
2、体系
小结
1、缓冲流的作用?
- 缓冲流自带缓冲区,可以提高原始字节流、字符流读写数据的性能。
2、缓冲流有几种?
- 字节缓冲流
- 字节缓冲输入流:BufferedInputStream
- 字节缓冲输出流:BufferedOutputStream
- 字符缓冲流
- 字符缓冲输入流:BufferedReader
- 字符缓冲输出流:BufferedWriter
3、字节缓冲流
- 字节缓冲输入流:BufferedInputStream,提高了字节输入流读取数据的性能,读写功能上并无变化。
- 字节缓冲输出流:BufferedOutputStream,提高了字节输出流读写数据的性能,读写功能上并无变化。
(1)字节缓冲流性能优化原理
- 字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能较好。
- 字节缓冲输出流自带了8KB缓冲流,数据就直接写入到缓冲池中去,写数据性能极高了。
(2)字节缓冲流构造器
构造器 | 说明 |
---|---|
public BufferedInputStream(InputStream is) | 可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道, 从而提高字节输入流读取数据的性能 |
public BufferedOutputStream(OutputStream os) | 可以把低级的字节输出流包装成一个高级的缓冲字节输出流管道, 从而提高字节输出流读写数据的性能 |
package com.app.d1_byte_buffer;
import java.io.*;
/**
目标:
掌握如何将低级的字节输入、输出流包装成一个高级的缓冲字节输入、输出流管道,
从而提高字节输入、输出流读取、读写数据的性能。
*/
public class ByteBufferDemo01 {
public static void main(String[] args) {
try (
// 1、创建一个字节输入流管道与源文件路径接通
InputStream is = new FileInputStream("E:\\JavaDevelop\\images\\3.jpg");
// a.把原始的字节输入流包装成高级的缓冲字节输入流管道
InputStream bis = new BufferedInputStream(is);
// 2、创建一个字节输出流管道与目标文件路径接通
OutputStream os = new FileOutputStream("E:\\JavaDevelop\\images\\4411.jpg");
// b.把原始的字节输出流包装成高级的缓冲字节输出流管道
OutputStream bos = new BufferedOutputStream(os);
) {
// 3、拷贝源文件到目标文件路径下
// 定义一个数组,用于每次读取1KB的字节数据
byte[] buffer = new byte[1024];
int len; // 用于记录每次读取的字节数
// 定义循环,不断读取源文件的字节数据,直到字节等于-1才结束
while ( (len = bis.read(buffer)) != -1 ) {
// 读取多少倒出多少
bos.write(buffer, 0, len);
}
System.out.println("拷贝完成!");
} catch (Exception e) {
e.printStackTrace();
System.out.println("拷贝失败!");
}
}
}
拷贝完成!
Process finished with exit code 0
小结
1、字节缓冲流为什么提高了操作数据的性能?
- 字节缓冲流自带8KB缓冲区;
- 可以提高原始字节流、字符流读写数据的性能。
2、字节缓冲流的功能如何调用?
4、字节缓冲流的性能分析
- 我们已经说明了字节缓冲流的性能高效,但是没有直接感受到!!
- 如何测试字节缓冲流的读写性能呢?
小范例:
分别使用不同的方式复制大视频观察性能情况!
需求:
- 分别使用低级字节流和高级字节缓冲流拷贝大视频,记录耗时。
分析:
1、使用低级的字节流按照一个一个字节的形式拷贝文件。
2、使用低级的字节流按照一个一个字节数组的形式拷贝文件。
3、使用高级的字节缓冲流按照一个一个字节的形式复制文件。
4、使用高级的字节缓冲流按照一个一个字节数组的形式拷贝文件。
package com.app.d2_byte_buffer_time;
import java.io.*;
/**
目标:通过使用不同方式的复制文件的形式观察基础字节流和高级字节缓冲流的性能区别
需求:
分别使用基础字节流和高级字节缓冲流拷贝文件,记录耗时。
*/
public class ByteBufferTimeDemo01 {
// 定义两个变量,用于记录源文件路径和目标文件路径
public static final String SRC_FILE = "E:/Python学习资源/Python视频类资料/Python入门视频/1-Python环境搭建/2-Python环境搭建.wmv";
public static final String DEST_FILE = "E:/Python学习资源/Python视频类资料/Python入门视频/1-Python环境搭建/测试1/";
public static void main(String[] args) {
// copy1(); // 使用基础字节流按照一个一个字节的形式拷贝文件:速度非常慢,无法忍受!性能差!(淘汰!)
copy2(); // 使用基础字节流按照一个一个字节数组的形式拷贝文件:速度比较慢,性能还行!(不推荐使用!)
copy3(); // 使用字节缓冲流按照一个一个字节的形式拷贝文件:速度太慢,性能差!(不推荐使用!)
copy4(); // 使用字节缓冲流按照一个一个字节数组的形式拷贝文件:速度飞快,性能ok!(推荐使用!!)
}
private static void copy4() {
// 记录拷贝开始时间
long startTime = System.currentTimeMillis();
try (
// 1、创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
// a.将基础字节输入流管道包装成字节缓冲输入流管道
InputStream bis = new BufferedInputStream(is);
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE + "test04.wmv");
// b.将基础字节输出流管道包装成字节缓冲输出流管道
OutputStream bos = new BufferedOutputStream(os);
) {
// 3、一个一个字节数组的形式拷贝文件
byte[] buffer = new byte[1024]; // 每次读取1KB的字节数
int len; // 记录每次读取的字节数
// 循环读取,读到-1结束循环
while ( (len = bis.read(buffer)) != -1 ) {
// 读多少取多少
bos.write(buffer, 0, len);
}
}catch (Exception e){
e.printStackTrace();
}
// 记录拷贝结束时间
long endTime = System.currentTimeMillis();
// 计算拷贝文件总耗时多少?
System.out.println("使用字节缓冲流按照一个一个字节数组的形式拷贝文件总耗时:" + (endTime - startTime)/1000.0 + "秒");
}
private static void copy3() {
// 记录拷贝开始时间
long startTime = System.currentTimeMillis();
try (
// 1、创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
// a.将基础字节输入流管道包装成字节缓冲输入流管道
InputStream bis = new BufferedInputStream(is);
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE + "test03.wmv");
// b.将基础字节输出流管道包装成字节缓冲输出流管道
OutputStream bos = new BufferedOutputStream(os);
) {
// 3、一个一个字节的形式拷贝文件
int len; // 记录每次读取的字节数
// 循环读取,读到-1结束循环
while ( (len = bis.read()) != -1 ) {
bos.write(len);
}
}catch (Exception e){
e.printStackTrace();
}
// 记录拷贝结束时间
long endTime = System.currentTimeMillis();
// 计算拷贝文件总耗时多少?
System.out.println("使用字节缓冲流按照一个一个字节的形式拷贝文件总耗时:" + (endTime - startTime)/1000.0 + "秒");
}
private static void copy2() {
// 记录拷贝开始时间
long startTime = System.currentTimeMillis();
try (
// 1、创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
// 2、创建一个字节输出流管道与源文件接通
OutputStream os = new FileOutputStream(DEST_FILE + "test02.wmv");
) {
// 3、一个一个字节数组的读取文件数据
byte[] buffer = new byte[1024]; // 每次读取1KB的字节数
int len; // 用于记录每次读取的字节数
// 循环读取,读到-1结束循环
while ( (len = is.read(buffer)) != -1 ) {
// 读多少取多少
os.write(buffer, 0, len);
}
}catch (Exception e) {
e.printStackTrace();
}
// 记录拷贝结束时间
long endTime = System.currentTimeMillis();
// 计算拷贝文件总耗时多少?
System.out.println("使用基础字节流按照一个一个字节数组的形式拷贝文件总耗时:" + (endTime - startTime)/1000.0 + "秒");
}
private static void copy1() {
// 记录拷贝开始时间
long startTime = System.currentTimeMillis();
try (
// 1、创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
// 2、创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE + "test01.wmv");
) {
// 3、一个一个字节的读取文件数据
int len; // 记录每次读取的字节数
// 循环读取,读到-1结束循环
while ( (len = is.read()) != -1 ) {
os.write(len);
}
}catch (Exception e) {
e.printStackTrace();
}
// 记录拷贝结束时间
long endTime = System.currentTimeMillis();
// 计算拷贝文件总耗时多少?
System.out.println("使用基础字节流按照一个一个字节的形式拷贝文件总耗时:" + (endTime - startTime)/1000.0 + "秒");
}
}
使用基础字节流按照一个一个字节数组的形式拷贝文件总耗时:2.032秒
使用字节缓冲流按照一个一个字节的形式拷贝文件总耗时:4.561秒
使用字节缓冲流按照一个一个字节数组的形式拷贝文件总耗时:1.033秒
Process finished with exit code 0
总结
1、推荐使用哪种方式提高字节流读写数据的性能?
- 建议使用字节缓冲输入、输出流,结合字节数组的形式,目前来看是性能最优的组合。