Maximilian. 2021-08-13 18:34 采纳率: 50%
浏览 35
已结题

为什么Java的缓冲流在复制文本文档内容上消耗的时间比普通的输入输出流长呢?

同为复制这样的文本文件(如图)

img

编写的代码如下:


import java.io.*;
import java.util.Scanner;

/**
 * @author Maximilian_Li
 */
public class TestEfficiency {
    public static void main(String[] args) throws IOException {
        String basicFilePath = "D:\\Java\\Note&Code\\Java_Network_Programming\\src\\Chapter01_Stream\\" +
                "Section03_BufferedStream\\";

        String filePathFrom = basicFilePath + "from.txt";

        String filePathTo = basicFilePath + "to.txt";

        File fromFile = new File(filePathFrom);
        File toFile = new File(filePathTo);

        while(true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("\r\n请输入你的选择(【1】代表普通输入输出流,【2】代表缓冲输入输出流)。\r\n");
            int anInt = sc.nextInt();

            switch (anInt) {
                case 1:
                    FileInputStream fromStream = new FileInputStream(fromFile);
                    FileOutputStream toStream = new FileOutputStream(toFile);

                    System.out.println("普通流所需时间  : " + timeOfOriginal(fromStream, toStream));

                    break;
                case 2:
                    BufferedReader buffFrom = new BufferedReader(new FileReader(fromFile));
                    BufferedWriter buffTo = new BufferedWriter(new FileWriter(toFile));

                    System.out.println("缓冲流所用时间  : " + timeOfBuffered(buffFrom, buffTo) + "\r\n");

                    break;
                default:
                    System.exit(0);
            }
        }
    }

    private static long timeOfBuffered(BufferedReader buffFrom, BufferedWriter buffTo) throws IOException {
        long startTime = System.currentTimeMillis();
        System.out.println(startTime);

        String aLine = null;
        while ((aLine = buffFrom.readLine()) != null) {
            buffTo.write(aLine);
            buffTo.newLine();
        }

        buffFrom.close();
        buffTo.close();

        long endTime = System.currentTimeMillis();
        System.out.println(endTime);

        return (endTime - startTime);
    }

    private static long timeOfOriginal(FileInputStream fromStream, FileOutputStream toStream) throws IOException {
        long startTime = System.currentTimeMillis();
        System.out.println(startTime);

        int length = 0;
        byte[] bytes = new byte[1024];

        while ((length = fromStream.read(bytes)) != -1) {
            toStream.write(bytes,0,length);
        }

        fromStream.close();
        toStream.close();

        long endTime = System.currentTimeMillis();
        System.out.println(endTime);

        return (endTime - startTime);
    }
}

输出结果为这样(如图)

img

但是据我了解,缓冲流的效率是远高于普通输入输出流的,为什么会出现这种状况呢?

  • 写回答

2条回答 默认 最新

  • 山河已无恙 云原生领域优质创作者 2021-08-14 10:35
    关注

    嗯,之前没有细看,只是觉得应该是这个原因,我的意思你读的东西太少了:

    • 比如你用数据库连接池和直接用JDBC连据库连。理论上连接池更好,因为多个连接不用建立关闭连接,直接用池里的,数据库连接的建立和关闭是耗费系统资源的操作。(同样IO也是消耗资源的事),但是现实情况是你连接一次。那还不如用JDBC了,时间上来讲,你还没有构建完连接池数据源对象,可能jdbc已经连接完成了。所以我说你这个可能是数据太少。

    看你回复了,我看了下代码:嗯,我没有那你的代码实际测试,下面是一些个人想法,你可以参考一下。

    首先你的复制方式都是边写边读的方式,区别在于:

    • FileInputStramd相关使用的是 批量拷贝(循环读取,每次读入一个byte数组)
    • BufferedReader相关使用的是批量+缓冲拷贝(循环批量读取到字节数组中,然后使用缓冲输出流写入到文件)

    但是这里有一个问题:你在使用BufferedWriter类的Writer方法时,数据并没有立刻写入输入流,而是首先进入缓存区中,如果想立刻缓存区中的数据写入输入流,一定要调用flush()方法。现在写到缓存区交给缓存流去写,如果数据很少的话,就没必要搞一个缓存流去写,太消耗时间了资源了。

    生成一个大文件,用你的代码测试一下:


    img


    如果你每次都调flush()去刷新的话,可以看出 ,建立缓存区消耗的时间很多。

    while ((aLine = buffFrom.readLine()) != null) {
                buffTo.write(aLine);
                buffTo.newLine();
                buffTo.flush();
            }
    

    img


    package com;
    
    /**
     * @Classname TestEfficiency
     * @Description TODO
     * @Date 2021/8/14 10:40
     * @Created LiRuilong
     */
    
    import java.io.*;
    import java.util.Scanner;
    /**
     * @author Maximilian_Li
     */
    public class TestEfficiency {
        public static void main(String[] args) throws Exception {
    
            String basicFilePath = "";
            System.out.println(basicFilePath);
            String filePathFrom = basicFilePath + "from.txt";
            String filePathTo = basicFilePath + "to.txt";
            File fromFile = new File(filePathFrom);
            File toFile = new File(filePathTo);
            System.out.println(fromFile.getAbsolutePath());
           /* fromFile.createNewFile();
            FileOutputStream fileOutputStream = new FileOutputStream(fromFile,true);
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
               fileOutputStream.write("请输入你的选择(【1】代表普通输入输出流,【2】代表缓冲输入输出流)。\n".getBytes());
            }*/
    
    
            while(true) {
                Scanner sc = new Scanner(System.in);
                System.out.println("\r\n请输入你的选择(【1】代表普通输入输出流,【2】代表缓冲输入输出流)。\r\n");
                int anInt = sc.nextInt();
                switch (anInt) {
                    case 1:
                        FileInputStream fromStream = new FileInputStream(fromFile);
                        FileOutputStream toStream = new FileOutputStream(toFile);
                        System.out.println("普通流所需时间  : " + timeOfOriginal(fromStream, toStream));
                        break;
                    case 2:
                        BufferedReader buffFrom = new BufferedReader(new FileReader(fromFile));
                        BufferedWriter buffTo = new BufferedWriter(new FileWriter(toFile));
                        System.out.println("缓冲流所用时间  : " + timeOfBuffered(buffFrom, buffTo) + "\r\n");
                        break;
                    default:
                        System.exit(0);
                }
            }
        }
        private static long timeOfBuffered(BufferedReader buffFrom, BufferedWriter buffTo) throws IOException {
            long startTime = System.currentTimeMillis();
            System.out.println(startTime);
            String aLine = null;
            buffFrom.close();
            buffTo.close();
            long endTime = System.currentTimeMillis();
            System.out.println(endTime);
            return (endTime - startTime);
        }
        private static long timeOfOriginal(FileInputStream fromStream, FileOutputStream toStream) throws IOException {
            long startTime = System.currentTimeMillis();
            System.out.println(startTime);
            int length = 0;
            byte[] bytes = new byte[1024];
            while ((length = fromStream.read(bytes)) != -1) {
                toStream.write(bytes,0,length);
            }
            fromStream.close();
            toStream.close();
            long endTime = System.currentTimeMillis();
            System.out.println(endTime);
            return (endTime - startTime);
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 8月23日
  • 已采纳回答 8月15日
  • 创建了问题 8月13日

悬赏问题

  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来