Logo

郎哥编程

支持缓存的输入与输出流

2021-07-09 261

学习目标:掌握具有缓存的输入和输出流。

支持缓存的输入与输出流

BufferedInputStream为带缓存的输入流,BufferedOutputStream为带缓存的输出流。缓存输入输出就是在读写磁盘文件之前,先把数据读取或写入到预先分配的内存区域(这片内存区域称为缓冲区),当缓冲区存储的数据已满时,再进行磁盘文件的读写操作。通过缓冲区读写文件带来的好处是可以优化程序的输入输出性能,提高程序读写磁盘文件的速度。

BufferedInputStream类的工作依赖于InputStream,它需要使用InputStream类进行磁盘文件的读写。BufferedInputStream读取文件的工作原理如下图所示:

30.png

BufferedInputStream类在内部维护一个缓冲区。实例化BufferedInputStream对象时,需要传入InputStream的实例化对象,当程序调用BufferedInputStream对象从文件读取数据时,它会先判断缓冲区是否有读取的文件数据,如果有就从缓冲区读取,否则就调用InputStream对象从文件读取数据填满缓冲区。

BufferedOutputStream类和BufferedInputStream类的工作原理是相同的,只不过一个是写入文件数据,一个是读取文件数据。BufferedOutputStream类在内部也维护一个缓冲区,当程序调用BufferedOutputStream将数据写入文件时,它会先把数据写入缓冲区,当缓冲区已满时,再调用OutputStream将缓冲区的数据写入到文件。BufferedOutputStream类也提供了flush()方法,可以强制将缓冲区的数据写入到文件。

(1)BufferedInputStream类

BufferedInputStream类有默认的缓冲区空间,程序可以在类的构造函数中传入需要的缓冲区空间大小。

BufferedInputStream类的构造函数如下:

●   public BufferedInputStream(InputStream in);

该构造函数创建具有默认缓冲区空间的输入流。

●   public BufferedInputStream(InputStream in, int size);

该构造函数创建指定缓冲区空间大小的输入流。

InputStream类是BufferedInputStream的父类,因此InputStream类定义的方法,BufferedInputStream都可以使用。

案例15:建立BufferedInputStreamTest测试类,读取图片文件。

在PUnit11项目新建buffer包,在buffer包下新建BufferedInputStreamTest类。代码如下:

package buffer;
 
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
 
public class BufferedInputStreamTest {
    public static void main(String[] args) {
        // 读取的图片文件路径
        String filename = "d:\\001.jpg";
        BufferedInputStream bufferedInput = null;
        // 申请读取文件的缓冲区
        byte[] buffer = new byte[1024];
 
        try {
 
            // 创建BufferedInputStream 对象
            bufferedInput = new BufferedInputStream(new FileInputStream(filename));
 
            int bytesRead = 0;
 
            // 从文件中按字节读取内容,到文件尾部时read方法将返回-1
            while ((bytesRead = bufferedInput.read(buffer)) != -1) {
 
                // 将读取的字节转为字符串对象
                String content = new String(buffer, 0, bytesRead);
                System.out.print(content);
            }
 
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            // 关闭 BufferedInputStream
            try {
                if (bufferedInput != null)
                    bufferedInput.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
 
    }
}

案例代码完成读取图片文件的操作,使用BufferedInputStream类的read方法将图片文件数据读入到buffer缓冲区,并将buffer缓冲区的输出到控制台。因为读取的图片文件是二进制文件,所以在控制台显示的是乱码。关闭文件放到了finally语句块,这样做的好处是不管是否发生文件读取异常,都会关闭已打开的文件资源。

(2)BufferedOutputStream类

BufferedOutputStream类有默认的缓冲区空间,程序可以在类的构造函数中传入需要的缓冲区空间大小。BufferedOutputStream类的构造函数如下:

●   public  BufferedOutputStream(OutputStream out);

该构造函数创建具有默认缓冲区空间的输出流。

●   BufferedOutputStream(OutputStream out, int size);

该构造函数创建指定缓冲区空间大小的输出流。

OutputStream类是BufferedOutputStream的父类,因此OutputStream类定义的方法,BufferedOutputStream都可以使用。

案例16:建立BufferedOutputStreamTest测试类,建立一个二进制文件,输出数据到新建的二进制文件。

在buffer包下新建BufferedOutputStrea

package buffer;
 
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class BufferedOutputStreamTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BufferedOutputStream bufferoutput = null;
        //写数据
        try {
            bufferoutput = new BufferedOutputStream(new FileOutputStream("d:\\outtest.dat")) ;
            // 将String对象的内容转换为字节数组,并写入文件
            bufferoutput.write("这是一个二进制文件".getBytes());
            System.out.println("文件创建成功");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("文件创建失败");
            e.printStackTrace();
        } finally {
            //释放资源
            try {
                bufferoutput.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
 
    }
}

案例代码创建一个二进制文件,并写入字符串对象的内容。虽然创建的是二进制文件,但使用记事本仍然可以看到写入的中文内容,因为新建的二进制文件存储的是中文内容的文字编码。

文本缓存输入类

BufferedReader类是文本缓存输入类,BufferedReader类的父类是Reader类,BufferedReader类具有缓存机制,工作原理和BufferedInputStream类相同。

BufferedReader类有默认的缓冲区空间,程序可以在类的构造函数中传入需要的缓冲区空间大小。

BufferedReader类的构造函数如下:

●   public BufferedReader(Reader in);

该构造函数创建具有默认缓冲区空间的文本输入流。

●   public BufferedReader(Reader in, int sz)

该构造函数创建指定缓冲区空间大小的文本输入流。

Reader类的方法在《输入输出流》一课中已介绍,BufferedReader类新增加了一个readLine()方法,该方法说明如下:

●   String readLine()

该方法从文本文件中读取一行数据。

案例17:建立BufferedReaderTest测试类,使用BufferedReader的readLine()方法按行读取文本文件。

在buffer包下新建BufferedReaderTest类。代码如下:

package buffer;
 
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
 
public class BufferedReaderTest {
    public static void main(String[] args) {
        // 读取的文本文件路径
        String filename = "d:\\sample1.txt";
        BufferedReader reader;
        String line;
        try {
            // 实例化BufferedReader对象
            reader = new BufferedReader(new FileReader(filename));
            // 按行读取
            while ((line = reader.readLine()) != null) {
                System.out.print(line + "\n");
            }
            // 关闭文件
            reader.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
    }
}

案例代码使用BufferedReader类的readLine()方法按行读取文本文件,并输出到控制台。

文本缓存输出类

BufferedWriter类是文本缓存输出类,BufferedWriter类的父类是Writer类,BufferedWriter类具有缓存机制,工作原理和BufferedOutputStream类相同。

BufferedWriter类有默认的缓冲区空间,程序可以在类的构造函数中传入需要的缓冲区空间大小。

BufferedWriter类的构造函数如下:

●   public BufferedWriter(Writer out)

该构造函数创建具有默认缓冲区空间的文本输出流。

●   public BufferedWriter(Writer out, int sz)

该构造函数创建指定缓冲区空间大小的文本输出流。

Writer类的方法在《输入输出流》一课中已介绍,BufferedWriter类新增加了一个newLine ()方法,该方法说明如下:

●   String newLine ()

该方法输出一个换行符到文本文件。

案例18:建立BufferedWriterTest测试类,使用BufferedWriter的write ()和newLine()方法写入数据到文本文件。

在buffer包下新建BufferedWriterTest类。代码如下:

package buffer;
 
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
 
public class BufferedWriterTest {
    public static void main(String[] args) {
        String filename = "d:\\poetry.txt";
        BufferedWriter bufferwriter = null;
        try {
            bufferwriter = new BufferedWriter(new FileWriter(filename));
            bufferwriter.write("故人西辞黄鹤楼,");
            // 写入换行符
            bufferwriter.newLine();
            bufferwriter.write("烟花三月下扬州。");
            // 写入换行符
            bufferwriter.newLine();
            bufferwriter.write("孤帆远影碧空尽,");
            // 写入换行符
            bufferwriter.newLine();
            bufferwriter.write("唯见长江天际流。");
            // 关闭流
            bufferwriter.close();
            System.out.println("文件写入成功");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
    }
}

案例代码在D盘下创建poetry.txt文本文件,并写入李白的一首诗,每写入一句诗,就调用newLine()方法写入一个换行符到文本文件。

代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论