文章目录
java 中的缓冲流
1 节点流和处理流
1.1 基本介绍
- 节点流可以从一个特定的数据源读写数据,如下:
数据源 | 字节流类 | 字符流类 |
---|---|---|
文件 | FileInputStream | FileReader |
内存(字节数组) | ByteArrayInputStream | CharArrayReader |
管道 | PipedInputStream | PipedReader |
- 处理流(又称包装流)通过装饰器模式对节点流或其他处理流进行封装,提供更强大的功能(如缓冲、类型转换、序列化),如下:
功能 | 字节处理流 | 字符处理流 |
---|---|---|
缓冲 | BufferedInputStream | BufferedReader |
数据类型转换 | DataInputStream | — |
字节与字符转换 | InputStreamReader | OutputStreamWriter |
对象序列化 | ObjectInputStream | — |
1.2 节点流和处理流一览表
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 | 流类型 |
---|---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer | 节点流 |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter | 节点流 |
访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter | 节点流 |
访问管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter | 节点流 |
访问字符串 | - | - | StringReader | StringWriter | 节点流 |
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter | 处理流 |
转换流 | InputStreamReader | OutputStreamWriter | - | - | 处理流 |
对象流 | ObjectInputStream | ObjectOutputStream | - | - | 处理流 |
过滤流基类 | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter | 处理流 |
打印流 | - | PrintStream | - | PrintWriter | 处理流 |
推回输入流 | PushbackInputStream | - | PushbackReader | - | 处理流 |
特殊数据流 | DataInputStream | DataOutputStream | - | - | 处理流 |
1.3 节点流和处理流的区别和联系
- 节点流是底层流,直接跟数据源相接。
- 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
- 处理流(包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连。
1.4 处理流功能的主要体现
- 性能优化:通过缓冲减少IO操作次数,提升效率
- 功能扩展:支持数据类型转换(如
DataInputStream
读写基本类型)、编码处理(如InputStreamReader
转换字节到字符)
2 BufferedReader 和 BufferedWriter
BufferedReader 和 BufferedWriter 属于字符流,是处理流的一种,是按照字符来读取数据的。
2.1 BufferedReader 介绍
BufferedReader 类的继承、实现关系如下图:
源码分析:
由上图可知,BufferedReader 在内部维护了一个 Reader 对象 in,可以用来接收,Reader及其子类。
案例讲解: 使用 BufferedReader 读取文本文件,并显示在控制台。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReader_ {
public static void main(String[] args) throws IOException {
//FileReader 是 Reader的子类
BufferedReader bfr = new BufferedReader(new FileReader("d:\\0\\second.txt"));
String line = null;
//readerLine()读取一行文本
//当返回null时表示文件读取完毕
while((line = bfr.readLine()) != null) {
System.out.println(line);
}
//关闭处理流时,只需要关闭外层流即可
//底层会自动的去关闭节点流FileReader
bufferedReader.close();
}
}
更加详细的使用方法可以去查阅官方文档: BufferedReader - Java17中文文档 - API参考文档 - 全栈行动派
2.2 BufferedWriter 的介绍
BufferedWriter
类的继承、实现关系如下图:
源码:
可以看到,BufferedWriter
和 BufferedReader
一样,在内部维护了一个 Writer
的对象 "out"
,可以用来接收,Writer
及其子类。
案例讲解:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWrite_ {
public static void main(String[] args) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("d:\\0\\a.txt"));
//new FileWriter("d:\\0\\a.txt")
//没有指定append,默认为false,以覆盖写入
bufferedWriter.write("熊老大认了");
bufferedWriter.newLine();
bufferedWriter.write("熊老大认了");
bufferedWriter.newLine();
bufferedWriter.close();
}
}
-
public void write(int c)
:写入单个字符。 -
public void write(char[] cbuf, int off, int len)
:写入字符数组的一部分。cbuf
- 字符数组off
- 开始读取字符的下标len
- 要写入的字符数
-
public void write(String s, int off, int len)
:写入字符串的一部分。s
- 要写入的字符串off
- 开始读取字符的下标len
- 要写入的字符数
-
public void newLine()
:写入行分隔符,即插入一行
2.3 使用 BufferedReader 和 BufferedWriter 实现对文件的复制
案例讲解: 使用 BufferedReader 和 BufferedWriter 实现对文本文件的复制。
注意: BufferedReader 和 BufferedWriter 是字符流,按字符进行操作。对于二进制文件:图片、视频、音频等文件,不要去进行操作,不然有可能对文件造成损坏。
import java.io.*;
public class BufferedCopy {
public static void main(String[] args) {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
bufferedReader = new BufferedReader(new FileReader("d:\\0\\second.txt"));
bufferedWriter = new BufferedWriter(new FileWriter("d:\\0\\second2.txt"));
String line;
while((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
//按行读取并不会读取文件中的换行符,
//所以需要我们读取一行后使用newLine()进行换行
bufferedWriter.newLine();
}
//bufferedWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (bufferedWriter != null)
bufferedWriter.close();
if (bufferedReader != null)
bufferedReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
3 BufferedInputStream 和 BufferedOutputStream 的介绍
BufferedInputStream 和 BufferedOutputStream 是字节流,是按字节来处理数据的。
3.1 BufferedInputStream 的介绍
BufferedInputStream 类的继承、实现关系如下图:
3.2 BufferedOutputStream 的介绍
BufferedOutputStream 类的继承、实现关系如下图:
3.3 使用 BufferedInputStream 和 BufferedOutputStream 进行文件的复制
案例讲解: 使用字节流完成对图片的复制。
字节流按字节处理文件,可以复制任何类型的文件。
import java.io.*;
public class BufferedInputCopy {
public static void main(String[] args) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
int readLen = 0;
byte[] bytes = new byte[1024];
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream("d:\\0\\1.png"));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("d:\\0\\3.png"));
while((readLen = bufferedInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes, 0, readLen);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if(bufferedOutputStream != null)
bufferedOutputStream.close();
if(bufferedInputStream != null)
bufferedInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}