任务描述
本关任务:把给定文件中的内容使用字节缓冲流复制到另外一个文件。
相关知识
之前我们学习了 InputStream(字节输入流)和 OutputStream (字节输出流),下面我们来了解一下它们的间接子类,BufferedInputStream (字节缓冲输入流)和 BufferedOutputStream(字节缓冲输出流)。
为什么要有缓冲流
缓冲流的作用是提升流的读取、写入的速度。原因在于它的内部有一个缓冲区(默认大小为 8M),用户从缓冲区(内存中)读取或者写入数据时,可以减少 IO 操作。
BufferedInputStream(字节缓冲输入流)
BufferedInputStream 是 FilterOutStream 的直接子类,而 FilterOutStream 又是 InputStream 的直接子类,所以 BufferedInputStream 是 InputStream 的间接子类。它是一个带有缓冲区的输入流,使用它可以提高我们的读取效率。因为它每次调用 read 方法的时候,会首先尝试从缓冲区里读取数据,若读取失败(缓冲区无可读数据),则选择从物理数据源(譬如文件)读取新数据(这里会尝试尽可能读取多的字节)放入到缓冲区中,最后再将缓冲区中的内容返回给用户。由于从缓冲区里读取数据远比直接从物理数据源(譬如文件)读取速度快,所以 BufferedInputStream 的效率很高!
BufferedInputStream 的构造方法
下表中是它的两个构造方法:
| 构造方法 | 说明 |
|---|---|
| BufferedInputStream(InputStream in) | 创建一个 BufferedInputStream 对象并保存其参数,即输入流 in,以便将来使用。 |
| BufferedInputStream(InputStream in, int size) | 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 |
构造方法使用示例:
public static void main(String[] args) throws IOException{// 默认缓冲区大小创建缓冲流BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\yy\\Desktop\\file"));// 指定缓冲区大小创建缓冲流BufferedInputStream bufferedInputStream1 = new BufferedInputStream(new FileInputStream("C:\\Users\\yy\\Desktop\\file"),1024);}从构造方法中我们可以知道,BufferedInputStream 没有无参构造方法,它必须传入一个 InputStream (一般是 FileInputStream )一起使用,以提高读写效率。 ######BufferedInputStream 的常用方法 以下是它的常用方法:
| 方法名 | 说明 |
|---|---|
| read() | 从字节输入流中读取一个字节 |
| read(byte[] b,int off,int len) | 从字节输入流中读取字节放入数组 b 中,off 为偏移量,len 为写入的字节数 |
| close() | 关闭流 |
read() 方法使用示例:
public static void main(String[] args) throws IOException{try(// 创建缓冲流对象,已知a.txt文件中的内容为abcBufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\yy\\Desktop\\d.txt"));) { int read;// 读取数据 while ((read = bufferedInputStream.read()) != -1) {System.out.print((char) read);}}}执行结果:
abcBufferedOutputStream(字节缓冲输出流)
BufferedOutputStream 是 FilterOutStream 的直接子类,而 FilterOutStream 又是 InputStream 的直接子类,所以 BufferedOutputStream 是 InputStream 的间接子类。它是一个带有缓冲区的输出流,通常使用它可以提高我们的输出效率。
BufferedOutputStream 构造方法
以下是它的构造方法:
| 构造方法 | 说明 |
|---|---|
| BufferedOutputStream(OutputStream out) | 创建一个新的缓冲输出流,以将数据写入指定的底层输出流 |
| BufferedOutputStream(OutputStream out,int size) | 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流 |
我们可以看到它的构造方法和 BufferedInputStream 是一样的,这里我们就不在举例了。
BufferedOutputStream 常用方法
| 方法名 | 说明 |
|---|---|
| write(int b) | 向输出流中输出一个字节 |
| write(byte[] b,int off,int len) | 将数组中部分数据写入缓冲输出流,off:数组偏移量,len:写入的字节数 |
| flush() | 刷新缓冲输出流,这迫使所有缓冲的字节被写出到底层输出流中 |
write(byte[] b,int off,int len) 方法使用示例:
public static void main(String[] args) throws IOException{try(// 创建缓冲流对象BufferedOutputStream bf= new BufferedOutputStream(new FileOutputStream("C:\\Users\\yy\\Desktop\\d.txt"));) {// 创建字节数组 byte[] bytes ={96,97,98,99,100};// 从数组中索引为1的位置写入2个数据bf.write(bytes,1,2);// 刷新缓冲区bf.flush();}}执行结果:在 d.txt 文件中写入了 ab。
- import java.io.*;
- import java.util.Scanner;
-
- public class FileTest {
-
- public static void main(String[] args) throws IOException {
- Scanner input = new Scanner(System.in); // 获取给定字符串
- String str = input.nextLine();
- // 请在Begin-End间编写完整代码
- /********** Begin **********/
- // 切割给定字符串,切割给定字符串,获取源文件路径和目标文件路径
- String[] array = str.split(",");
- InputStream inputStream = new FileInputStream(array[0]);
- OutputStream outputStream = new FileOutputStream(array[1]);
- File file = new File(array[0]);
- // 创建缓冲流对象,实现文件复制
- byte[] bytes = new byte[Math.toIntExact(file.length())];
- try (
- BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);){
- while (bufferedInputStream.read(bytes) != -1);
- }
- try (
- BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);) {
- bufferedOutputStream.write(bytes);
- }
- // 输出目标文件长度
- System.out.println("文件长度:" + file.length());
- // for (int i = 0; i < bytes.length; i ++){
- // System.out.print((char) bytes[i]);
- // }
- /********** End **********/
- }
- }