缓冲流

除了字节输入/输出流、字符输入/输出流这四种输出流以外,还有一些更强大的流。

比如能高速读写的缓冲流,能够转换编码的转换流,能够持久化存储对象的序列化流等等

这些更为强大的流都是在基本的流对象基础之上创建而来的,就像穿上铠甲的武士一样,相当于是对基本的流对象的一种增强。


缓冲流原理


缓冲流也叫高效流,是对四个基本File流对象的增强【字节输入/输出流、字符输入/输出流】,所以缓冲流也是四个流。

缓冲流按数据类型分类:

  • 字节缓冲流:BufferedInputStrem,BufferedOutptStrem
  • 字符缓冲流:BufferedReader,BufferedWriter

缓冲流基本原理:在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。


字节缓冲流

BufferedOutputStream:字节缓冲输出流

构造方法

  • BufferedOutputStream(OutputStream out)
    创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
  • BufferedOutputStream(OutputStream out, int size)
    创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。

参数

  • OutputStream out:字节输出流 传入一个FileOutputStream,缓冲流就会给FileOutputStream增加一个缓冲区,提高FileOutputStream的写入效率
  • int size:指定缓冲流的内部缓冲区大小,如果不指定,就是默认大小

使用步骤

  1. 创建一个字节输出流对象FileOutputStream,构造方法中绑定要输出的目的地
  2. 创建字节缓冲流对象BufferedOutputStream,构造方法中传递字节输出流对象FileOutputStream,提高FileOutputStream的写入效率
  3. 使用BufferedOutputStream中的方法write,把数据写入到内部缓冲区中
  4. 使用BufferedOutputStream中的方法flush,把内部缓冲区中的数据刷新到文件中
  5. 释放资源(会先调用flush方法刷新数据,第4步可以省略)
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
    java.lang.Object
  继承者 java.io.OutputStream
      继承者 java.io.FilterOutputStream
          继承者 java.io.BufferedOutputStream

    BufferedOutputStream:字节缓冲输出流

    继承自父类的共性成员方法:
        void close() 关闭此输出流并释放与此流有关的所有系统资源。
        void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
        void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
        void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
        abstract  void write(int b) 将指定的字节写入此输出流。

    构造方法:
        BufferedOutputStream(OutputStream out)
          创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
        BufferedOutputStream(OutputStream out, int size)
          创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
    参数:
        OutputStream out:字节输出流 传入一个FileOutputStream,缓冲流就会给FileOutputStream增加一个缓冲区,提高FileOutputStream的写入效率
        int size:指定缓冲流的内部缓冲区大小,如果不指定,就是默认大小

    使用步骤:
        1.创建一个字节输出流对象FileOutputStream,构造方法中绑定要输出的目的地
        2.创建字节缓冲流对象BufferedOutputStream,构造方法中传递字节输出流对象FileOutputStream,提高FileOutputStream的写入效率
        3.使用BufferedOutputStream中的方法write,把数据写入到内部缓冲区中
        4.使用BufferedOutputStream中的方法flush,把内部缓冲区中的数据刷新到文件中
        5.释放资源(会先调用flush方法刷新数据,第4步可以省略)

 */
public class DemosBuffered1 {
    public static void main(String[] args) throws IOException {
        show1();
    }

    private static void show1() throws IOException {
        FileOutputStream fos = new FileOutputStream("FileAndIO\src\main\java\abc.txt\a.txt",true);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        bos.write(97);//a
        bos.flush();
        bos.close();
    }
}


BufferedInputStream:字节缓冲输入流

构造方法

  • BufferedInputStream(InputStream in)
    创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
  • BufferedInputStream(InputStream in, int size)
    创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

小贴士

不同编码方式1个英文字母占的字节是不同的:

  1. ASCII码:英文字母(无大小写)占一个字节的空间,中文字符占两个字节的空间。
  2. utf-8编码:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。中文的标点符号需要三个字节,英文的标点符号需要一个字节。
  3. Unicode编码:英文编码是两个字节,中文编码是两个字节。标点符号在汉语中占两个字节,在英语中占两个字节。
  • read() : 从输入流中读取数据的下一个字节,返回0到255范围内的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回-1。在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。
  • read(byte[] b) : 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取字节数。在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。

每次读取单个字节

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

/*
    java.lang.Object
  继承者 java.io.InputStream
      继承者 java.io.FilterInputStream
          继承者 java.io.BufferedInputStream

    BufferedInputStream:字节缓冲输入流

    继承自父类的共性成员方法:
        int read()从输入流中读取数据的下一个字节
        int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
        void close() 关闭此输入流并释放与该流关联的所有资源

    构造方法:
        BufferedInputStream(InputStream in)
          创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
        BufferedInputStream(InputStream in, int size)
          创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

    参数:
        InputStream in:字节输入流 传入一个FileInputStream,缓冲流就会给FileInputStream增加一个缓冲区,提高FileInputStream的读取效率
        int size:指定缓冲流的内部缓冲区大小,如果不指定,就是默认大小

    使用步骤:
        1.创建一个字节输出流对象FileInputStream,构造方法中绑定要读取的数据源
        2.创建字节缓冲流对象BufferedInputStream,构造方法中传递字节输出流对象FileInputStream,提高FileInputStream的读取效率
        3.使用BufferedInputStream中的方法read,读取文件
        4.释放资源

 */
public class DemosBuffered2 {
    public static void main(String[] args) throws IOException {
        show1();
    }

    private static void show1() throws IOException {
        FileInputStream fis = new FileInputStream("FileAndIO\src\main\java\abc.txt\a.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
//        int read = bis.read();//一次读一个字节
        //利用while循环读取整个文件
        int len = 0;
        while ((len = bis.read())!=-1){
            System.out.print(len);
        }
        bis.close();
    }
}

每次读取自定义字节个数

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

/*
    java.lang.Object
  继承者 java.io.InputStream
      继承者 java.io.FilterInputStream
          继承者 java.io.BufferedInputStream

    BufferedInputStream:字节缓冲输入流

    继承自父类的共性成员方法:
        int read()从输入流中读取数据的下一个字节
        int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
        void close() 关闭此输入流并释放与该流关联的所有资源

    构造方法:
        BufferedInputStream(InputStream in)
          创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
        BufferedInputStream(InputStream in, int size)
          创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

    参数:
        InputStream in:字节输入流 传入一个FileInputStream,缓冲流就会给FileInputStream增加一个缓冲区,提高FileInputStream的读取效率
        int size:指定缓冲流的内部缓冲区大小,如果不指定,就是默认大小

    使用步骤:
        1.创建一个字节输入流对象FileInputStream,构造方法中绑定要读取的数据源
        2.创建字节缓冲输入流对象BufferedInputStream,构造方法中传递字节输入流对象FileInputStream,提高FileInputStream的读取效率
        3.使用BufferedInputStream中的方法read,读取文件
        4.释放资源

 */
public class DemosBuffered2 {
    public static void main(String[] args) throws IOException {
        show1();
    }

    private static void show1() throws IOException {
        FileInputStream fis = new FileInputStream("FileAndIO\src\main\java\abc.txt\a.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
//        int read = bis.read();
        //利用while循环读取整个文件【且一次读取自定义字节个数】
        int len = 0;
        byte[] bytes = new byte[1024];//每次读取1024个字节,可提高读取效率
        while ((len = bis.read(bytes))!=-1){
            System.out.println(len);//a.txt文件中字节个数为36
            System.out.print(new String(bytes,0,len));
        }
        bis.close();
    }
}

字节缓冲流复制粘贴图片【效率更高了】

import java.io.*;


public class DemosBufferedCopy {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();//开始计时(用来计算程序执行时间)
        //注意:读的文件是什么格式,写的目的地就要是什么格式的文件,写的目的地不能是文件夹
        FileInputStream fis = new FileInputStream("C:\Users\98398\Desktop\我的截图\wallhaven-o333pp.jpg");//要复制的图片的地址
        BufferedInputStream bis = new BufferedInputStream(fis);
        FileOutputStream fos = new FileOutputStream("E:\IdeaProjects\spring-study\FileAndIO\src\main\java\abc.txt\3.jpg");//粘贴图片目的地的地址【必须有一个图片格式的文件地址】
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = bis.read(bytes))!=-1){
            bos.write(bytes,0,len);
        }
        //释放资源(先关闭写的,后关闭读的)
        bos.close();
        bis.close();
        long end = System.currentTimeMillis();//结束计时(用来计算程序执行时间)
        System.out.println("复制文件耗时"+(end-start)+"ms");
    }
}

字符缓冲流

BufferedWriter:字符缓冲输出流

java.lang.Object
继承者 java.io.Writer
继承者 java.io.BufferedWriter

继承自父类的共性成员方法

  1. abstract void close() 关闭此流,但要先刷新它。
  2. abstract void flush() 刷新该流的缓冲。
  3. void write(char[] cbuf) 写入字符数组。
  4. abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
  5. void write(int c) 写入单个字符。
  6. void write(String str) 写入字符串。
  7. void write(String str, int off, int len) 写入字符串的某一部。

构造方法

  • BufferedWriter(Writer out)
    创建一个使用默认大小输出缓冲区的缓冲字符输出流。
  • BufferedWriter(Writer out, int sz)
    创建一个使用给定大小输出缓冲区的新缓冲字符输出流。

参数

  • Writer out:一个字符输出流,传递一个FileWriter,缓冲流会给FileWriter增加一个缓冲区,提高FileWriter的写入效率
  • int sz:指定缓冲区的大小,不写就是默认大小

字符缓冲输出流BufferedWriter特有的成员方法

  • void newLine()
    写入一个行分隔符。 会更具不同的操作系统获取不同的行分隔符

使用步骤

  1. 创建一个字符输出流对象FileOutputStream,构造方法中绑定要输出的目的地
  2. 创建字符缓冲输出流对象BufferedWriter,构造方法中传递字符输出流对象FileOutputStream,提高FileOutputStream的读取效率
  3. 使用BufferedWriter中的方法write,把数据写入到内存缓冲区中
  4. 调用字符缓冲输出流中的方法flush,把内存缓冲区中的数据书信到文件中
  5. 释放资源

import java.io.*;

/*
    BufferedWriter:字符缓冲输出流

        java.lang.Object
          继承者 java.io.Writer
              继承者 java.io.BufferedWriter

    继承自父类的共性成员方法:
        abstract  void close() 关闭此流,但要先刷新它。
        abstract  void flush() 刷新该流的缓冲。
        void write(char[] cbuf) 写入字符数组。
        abstract  void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
        void write(int c) 写入单个字符。
        void write(String str) 写入字符串。
        void write(String str, int off, int len)== 写入字符串的某一部。

    构造方法:
        BufferedWriter(Writer out)
            创建一个使用默认大小输出缓冲区的缓冲字符输出流。
        BufferedWriter(Writer out, int sz)
            创建一个使用给定大小输出缓冲区的新缓冲字符输出流。

    参数:
        Writer out:一个字符输出流,传递一个FileWriter,缓冲流会给FileWriter增加一个缓冲区,提高FileWriter的写入效率
        int sz:指定缓冲区的大小,不写就是默认大小

    字符缓冲输出流BufferedWriter特有的成员方法
        void newLine()
            写入一个行分隔符。 会更具不同的操作系统获取不同的行分隔符

    使用步骤
        1. 创建一个字符输出流对象FileOutputStream,构造方法中绑定要输出的目的地
        2. 创建字符缓冲输出流对象BufferedWriter,构造方法中传递字符输出流对象FileOutputStream,提高FileOutputStream的读取效率
        3. 使用BufferedWriter中的方法write,把数据写入到内存缓冲区中
        4. 调用字符缓冲输出流中的方法flush,把内存缓冲区中的数据书信到文件中
        5. 释放资源
 */
public class DemosBufferedWriter {
    public static void main(String[] args) throws IOException {
        show1();
    }

    private static void show1() throws IOException {
        FileWriter fw = new FileWriter("FileAndIO\src\main\java\abc.txt\a.txt",true);
        BufferedWriter bw = new BufferedWriter(fw);
        for (int i = 0; i < 10; i++) {
//            bw.write("rn");//每次写入数据并换行
            bw.newLine();//换行
            bw.write("追写的数据");
        }
        bw.flush();
        bw.close();
    }
}

字符缓冲输入流

java.lang.Object
继承者 java.io.Reader
继承者 java.io.BufferedReader

继承自父类的共性成员方法

  1. int read() 读取单个字符并返回
  2. int read(char[] cbuf)一次读取多个字符,将字符读入数组
  3. void close() 关闭此输入流并释放与该流关联的所有资源

构造方法

  • BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
  • BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。

参数

  1. Reader in:一个字符输入流,传递一个FileReader,缓冲流会给FileReader增加一个缓冲区,提高FileReader的读取效率
  2. int sz:指定缓冲区的大小,不写就是默认大小

字符缓冲输入流BufferedReader特有的成员方法

  • ​ void readLine()
    ​ 读取一行文本。读取一行数据
    ​ 行的终符号:通过下列字符之一即可认为某行已终止:换行 ('n')、回车 ('r') 或回车后直接跟着换行。

返回值

  • 包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

使用步骤

  1. 创建一个字符输入流对象FileInputStream,构造方法中绑定要读取的数据源
  2. 创建字符缓冲输入流对象BufferedReader,构造方法中传递字符输入流对象FileInputStream,提高FileInputStream的读取效率
  3. 使用BufferedReader中的方法read/readLine,读取文本
  4. 释放资源
import java.io.*;

/*
    BufferedReader:字符缓冲输入流

        java.lang.Object
          继承者 java.io.Reader
              继承者 java.io.BufferedReader

    继承自父类的共性成员方法:
        int read() 读取单个字符并返回
        int read(char[] cbuf)一次读取多个字符,将字符读入数组
        void close() 关闭此输入流并释放与该流关联的所有资源
    构造方法:
        BufferedReader(Reader in)   创建一个使用默认大小输入缓冲区的缓冲字符输入流。
        BufferedReader(Reader in, int sz)   创建一个使用指定大小输入缓冲区的缓冲字符输入流。


    参数:
        Reader in:一个字符输入流,传递一个FileReader,缓冲流会给FileReader增加一个缓冲区,提高FileReader的读取效率
        int sz:指定缓冲区的大小,不写就是默认大小

    字符缓冲输入流BufferedReader特有的成员方法
        void readLine()
            读取一行文本。读取一行数据
                行的终符号:通过下列字符之一即可认为某行已终止:换行 ('n')、回车 ('r') 或回车后直接跟着换行。

    返回值:
        包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

    使用步骤
        1. 创建一个字符输入流对象FileInputStream,构造方法中绑定要读取的数据源
        2. 创建字符缓冲输入流对象BufferedReader,构造方法中传递字符输入流对象FileInputStream,提高FileInputStream的读取效率
        3. 使用BufferedReader中的方法read/readLine,读取文本
        4. 释放资源
 */
public class DemosBufferedReader {
    public static void main(String[] args) throws IOException {
        show1();
    }

    private static void show1() throws IOException {
        FileReader fr = new FileReader("FileAndIO\src\main\java\abc.txt\a.txt");
        BufferedReader br = new BufferedReader(fr);
//        String line = br.readLine();//读取一行代码
//        System.out.println(line);

        //while循环读取整个文件
        String line1;
        while ((line1 = br.readLine())!=null){
            System.out.println(line1);
        }
        //释放资源
        br.close();
    }
}

练习

对文本内容进行排序

3.醉不成欢惨将别,别时茫茫江浸月。
1.浔阳江头夜送客,枫叶荻花秋瑟瑟。
6.移船相近邀相见,添酒回灯重开宴。
4.忽闻水上琵琶声,主人忘归客不发.
2.主人下马客在船,举酒欲饮无管弦。
7.千呼万唤始出来,犹抱琵琶半遮面。
5.寻声暗问弹者谁?琵琶声停欲语迟。

import java.io.*;
import java.util.HashMap;

/*
    练习:
        对文本内容进行排序
        按照(1,2,3,4,5,6...)顺序排序
    分析:
        1.创建一个HashMap集合对象,可以:存储每行文本的序号(1,2,3,...)value:存储每行文本内容
        2.创建字符缓冲输入流对象,构造方法中绑定字符输入流
        3.创建字符缓冲输出流对象,构造方法中绑定字符输出流
        4.使用字符缓冲输入流中的方法readLine(),逐行读取文本
        5.对读取到的文本进行切割,获取行号中的序号和文本内容
        6.把切割好的序号和文本的内容存储到HashMap集合中(key的序号是有序的,会自动排序1,2,3,4,...)
        7.遍历HashMap集合,获取每一个键值对
        8.把每一个键值对,拼接为一个文本行
        9.把拼接好的文本行,使用字符缓冲输出流中的方法write,写入到文件中
        10.释放资源

    小贴士:
        split() 方法根据匹配给定的正则表达式来拆分字符串。
        注意: . 、 $、 | 和 * 等转义字符,必须得加 \。
        注意:多个分隔符,可以用 | 作为连字符。

        语法
        public String[] split(String regex, int limit)
        参数
        regex -- 正则表达式分隔符。
        limit -- 分割的份数。

        返回值
        字符串数组。

 */
public class IO练习_文本排序 {
    public static void main(String[]   args) throws IOException {
        HashMap<String, String> map = new HashMap<>();
        BufferedReader br = new BufferedReader(new FileReader("FileAndIO\src\main\java\abc.txt\g.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("FileAndIO\src\main\java\abc.txt\h.txt"));
        String line;
        while ((line = br.readLine())!=null){
            //分割每一行
            String[] arr = line.split("\.");
            //每行,分割开后是(序号,内容)
            for (String s : arr) {
                System.out.println(s);
            }
            map.put(arr[0],arr[1]);
        }
        for (String key :map.keySet()) {
            String value = map.get(key);
            line = key + "." + value;
            bw.write(line);
            bw.newLine();//换行
        }
        bw.close();
        br.close();
    }
}

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/niuniu-/p/14735466.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!

相关课程