JAVA 缓冲流 BufferedInputStream-BufferedOutputStream-BufferedReader-BufferedWriter

1. 概述

缓冲流,也叫高效流,缓冲流是相比字节流、字符流具有更高读写性能的操作流,其中包括:

  • 字节缓冲流BufferedInputStreamBufferedOutputStream
  • 字符缓冲流BufferedReaderBufferedWriter

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

2. 字节缓冲流

构造方法

  • public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。
  • public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流。

构造举例,代码如下:

// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(n
ew FileOutputStream("bos.txt"));

效率测试

查询API,缓冲流读写方法与基本的流是一致的,我们通过复制大文件(375MB),测试它的效率。

  1. 基本流,代码如下:
public class BufferedDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // 记录开始时间
      	long start = System.currentTimeMillis();
		// 创建流对象
        try (
        	FileInputStream fis = new FileInputStream("jdk9.exe");
        	FileOutputStream fos = new FileOutputStream("copy.exe")
        ){
        	// 读写数据
            int b;
            while ((b = fis.read()) != -1) {
                fos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		// 记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("普通流复制时间:"+(end - start)+" 毫秒");
    }
}

十几分钟过去了...
  1. 缓冲流,代码如下:
public class BufferedDemo {
    public static void main(String[] args) throws FileNotFoundException {
        // 记录开始时间
      	long start = System.currentTimeMillis();
		// 创建流对象
        try (
        	BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk9.exe"));
	     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
        ){
        // 读写数据
            int b;
            while ((b = bis.read()) != -1) {
                bos.write(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		// 记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("缓冲流复制时间:"+(end - start)+" 毫秒");
    }
}

缓冲流复制时间:8016 毫秒

如何更快呢?

使用数组的方式,代码如下:

public class BufferedDemo {
    public static void main(String[] args) throws FileNotFoundException {
      	// 记录开始时间
        long start = System.currentTimeMillis();
		// 创建流对象
        try (
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk9.exe"));
		 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
        ){
          	// 读写数据
            int len;
            byte[] bytes = new byte[8*1024];
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0 , len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		// 记录结束时间
        long end = System.currentTimeMillis();
        System.out.println("缓冲流使用数组复制时间:"+(end - start)+" 毫秒");
    }
}
缓冲流使用数组复制时间:666 毫秒

3. 字符缓冲流

构造方法

  • public BufferedReader(Reader in) :创建一个 新的缓冲输入流。
  • public BufferedWriter(Writer out): 创建一个新的缓冲输出流。

构造举例,代码如下:

// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

特有方法

字符缓冲流的基本方法与普通字符流调用方式一致,不再阐述,我们来看它们具备的特有方法。

  • BufferedReader:public String readLine(): 读一行文字。
  • BufferedWriter:public void newLine(): 写一行行分隔符,由系统属性定义符号。

readLine方法演示,代码如下:

public class BufferedReaderDemo {
    public static void main(String[] args) throws IOException {
      	 // 创建流对象
        BufferedReader br = new BufferedReader(new FileReader("in.txt"));
		// 定义字符串,保存读取的一行文字
        String line  = null;
      	// 循环读取,读取到最后返回null
        while ((line = br.readLine())!=null) {
            System.out.print(line);
            System.out.println("------");
        }
		// 释放资源
        br.close();
    }
}

newLine方法演示,代码如下:

public class BufferedWriterDemo throws IOException {
  public static void main(String[] args) throws IOException  {
    	// 创建流对象
  	BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
    	// 写出数据
      bw.write("高级");
    	// 写出换行
      bw.newLine();
      bw.write("程序");
      bw.newLine();
      bw.write("员");
      bw.newLine();
  	// 释放资源
      bw.close();
  }
}
输出效果:
高级
程序
员

4. 案例实现:文本排序

请将文本信息恢复顺序。

5.烹羊宰牛且为乐,会须一饮三百杯。
2.君不见高堂明镜悲白发,朝如青丝暮成雪。
10.陈王昔时宴平乐,斗酒十千恣欢谑。
3.人生得意须尽欢,莫使金樽空对月。
4.天生我材必有用,千金散尽还复来。
8.钟鼓馔玉不足贵,但愿长醉不愿醒。
12.五花马、千金裘,呼儿将出换美酒,与尔同销万古愁。
7.与君歌一曲,请君为我倾耳听。
6.岑夫子,丹丘生,将进酒,杯莫停。
9.古来圣贤皆寂寞,惟有饮者留其名。
11.主人何为言少钱,径须沽取对君酌。
1.君不见黄河之水天上来,奔流到海不复回。

案例分析

  1. 逐行读取文本信息。
  2. 解析文本信息到集合中。(利用HashMap的特性:会根据键进行排序
  3. 遍历集合,按顺序,写出文本信息。

案例实现

public static void main(String[] args) {
    Map<Integer, String> poem = new HashMap<>();
    try(BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\87828\\Desktop\\poem.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\87828\\Desktop\\sortPoem.txt"));){
        String line;
        while ((line = br.readLine()) != null){
            String arr[] = line.split("\\.");
            poem.put(Integer.valueOf(arr[0]), arr[1]);
        }

        for(Integer key : poem.keySet()){
            bw.write(key + "." + poem.get(key));
            bw.newLine();
        }
    }catch (IOException e){
        e.printStackTrace();
    }
}

结果:
在这里插入图片描述
注意:也可以用Map<String, String>类型,但是在排序的时候,字符串类型下:1和11会排在一起,然后再是2开头的。

发布了16 篇原创文章 · 获赞 6 · 访问量 812

猜你喜欢

转载自blog.csdn.net/weixin_43838446/article/details/104902141