[转载] FileInputStream 与 BufferedInputStream 效率对比

【问题】

FileInputStream & FileOutputStream 和 BufferedInputStream & BufferedOutputStream 都能完成文件的读写。它们在原理上、时间效率上有什么不同,实际应用时应该如何选择呢?

【实验】

我们采用文件复制来做效率对比的实验。

在FileOperator类的copyWithFileStream方法实现了使用FileInputStream和FileOutputStream复制文件,copyWithBufferedStream方法实现了使用BufferedInputStream和BufferedOutputStream复制文件。

复制代码

/*
 * Copyright (c) 2014 xxx.com. All Rights Reserved.
 */

package utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author ham.hog created on 2014 14-2-12 下午2:58
 * @version 0
 */
public class FileOperator {

    /** buffer size in bytes */
    final static int BUFFER_SIZE = 100;

    /**
     * copy file using FileInputStream & FileOutputStream

     * @param src copy from
     * @param dest copy to

     * @return;
     */
    public static void copyWithFileStream(File src, File dest){
        FileInputStream input = null;
        FileOutputStream output = null;

        try {
            input = new FileInputStream(src);
            output = new FileOutputStream(dest);

            byte[] buffer = new byte[BUFFER_SIZE];
            int copySize;

            while ((copySize = input.read(buffer)) > 0){
                output.write(buffer, 0, copySize);
                output.flush();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * copy file using BufferedInputStream & BufferedOutputStream

     * @param src copy from file
     * @param dest copy to file

     * @return;
     */
    public static void copyWithBufferedStream(File src, File dest){
        BufferedInputStream bufferedInput = null;
        BufferedOutputStream bufferedOutput = null;
        try {
            bufferedInput = new BufferedInputStream(new FileInputStream(src));
            bufferedOutput = new BufferedOutputStream(new FileOutputStream(dest));

            byte[] buffer = new byte[BUFFER_SIZE];
            int copySize;

            while ((copySize = bufferedInput.read(buffer)) > 0){
                bufferedOutput.write(buffer, 0, copySize);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bufferedInput.close();
                bufferedOutput.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

class FileOperatorTest{
    public static void main(String args[]){
        File src = new File("test.txt");
        File dest = new File("copyTest.txt");

        try {
            if (!dest.exists()){
                dest.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        //test copy using FileStream
        int startTime = System.currentTimeMillis();

        FileOperator.copyWithFileStream(src, dest);

        int endTime = System.currentTimeMillis();
        System.out.println("Copy file using FileStream takes : " + (endTime - startTime) + " ms.");

        //test copy using BufferedStream
        startTime = System.currentTimeMillis();

        FileOperator.copyWithBufferedStream(src, dest);

        endTime = System.currentTimeMillis();
        System.out.println("Copy file using BufferedStream takes : " + (endTime - startTime) + " ms.");
    }
}

复制代码

【运行结果】
测试文件大小约为900M,以下是在设定BUFFER_SIZE为不同值时的一次执行结果:

BUFFER_SIZE = 100
Copy file using FileStream takes: 42680 ms.
Copy file using BufferedStream takes: 2407 ms.

BUFFER_SIZE = 8192
Copy file using FileStream takes: 1689 ms.
Copy file using BufferedStream takes: 1654 ms.

BUFFER_SIZE = 1000000
Copy file using FileStream takes: 957 ms.
Copy file using BufferedStream takes: 929 ms.

 

【对时间效率差异的解释】
BufferedInputStream比FileInputStream多了一个缓冲区,执行read时先从缓冲区读取,当缓冲区数据读完时再把缓冲区填满。
因此,当每次读取的数据量很小时,FileInputStream每次都是从硬盘读入,而BufferedInputStream大部分是从缓冲区读入。读取内存速度比读取硬盘速度快得多,因此BufferedInputStream效率高。
BufferedInputStream的默认缓冲区大小是8192字节。当每次读取数据量接近或远超这个值时,两者效率就没有明显差别了。
BufferedOutputStream和FileOutputStream同理,差异更明显一些。

 

【结论】

一般情况下,我们应该优先选取BufferedInputStream&BufferedOutputStream。

注意       File file = new File(new File(parent), path);//此处如果文件不存在,不会创建文件

当执行write操作的时候如果文件不存在则会创建文件.

public final T parseFromFile(String parent, String path) {
        File file = new File(new File(parent), path);
        File file2 = new File(new File(Environment.getExternalStorageDirectory().getPath()), "file2");
        File file3 = new File(new File(Environment.getExternalStorageDirectory().getPath()), "file3");


        BufferedInputStream bis = null;
        byte[] ad = new byte[4];

        try {
            FileInputStream fis = new FileInputStream(file);
            new FileOutputStream(file3).write(1);//会新建文件
            new FileInputStream(file2).read();//不会新建文件
            bis = new BufferedInputStream(fis, 25);//只开25字节的buffer
            return parseFromStream(path, bis);
        } catch (FileNotFoundException e) {
            Timber.tag(TAG).e(e, "File not found for parent:%s path:%s", parent,
                    path);
        } catch (IOException e) {
            Timber.tag(TAG).e(e, "IO error for parent:%s path:%s", parent, path);
        } finally {
            IoUtils.closeQuietly(bis);
        }
        return null;
    }

 

 

你可能感兴趣的:([转载] FileInputStream 与 BufferedInputStream 效率对比)