文件读写效率总结


文件的读主要考虑:FileInputStream和BufferedInputStream两种输入流,对应的输出流是FileOutputStream和BufferedOutputStream两种输出流。


常规认为BufferedInputStream/BufferedOutputStream是处理流,自带大小为8192(8K)字节的缓冲区,效率会比FileInputStream/FileOutputStream的效率高。但是这种简单的比较是错误的,需要制定一定条件进行比较。下面就两种方式在不同情况下效率比较做一个总结。其中还有未解决的问题,希望大神给出解答。


fin->FileInputStream,fo->FileOutputStream;bfin->BufferedInputStream,bfo->BufferedOutputStream


(1)单字节处理,不指定缓冲区


//不指定缓冲区遍历输入
 

  fo.write(fin.read());} 

 

  ---------------------------------------- 

 
//不指定缓冲区遍历输入
 

  bfo.write(bfin.read());}


文件复制速度:fin(0.26M/s),bfin(0.7M/s),文件2G以内


========================================================


//不指定缓冲区,不遍历输入


fo.write(temp);}


----------------------------------------


//不指定缓冲区,不遍历输入


bfo.write(temp);}


文件复制速度:fin(0.47M/s),bfin(18M/s)文件2G以内


=======================================================


(2)多字节处理,指定缓冲区


//缓冲区为1个字节


while((fin.read(b)) != -1) {


fo.write(b);}


----------------------------------------------


while((bfin.read(b)) != -1) {


bfo.write(b);


文件复制速度:fin(0.47M/s),bfin(18M/s)文件2G以内


=========================================================


byte[] b = new byte[10];//缓冲区为10个字节


文件复制速度:fin(4.7M/s),bfin(135M/s)文件2G以内


======================================================


byte[] b = new byte[100];//缓冲区为100个字节


文件复制速度:fin(13.3M/s),bfin(315M/s)文件2G以内


======================================================


byte[] b = new byte[1024];//缓冲区为1024个字节


文件复制速度:fin文件2G以内(255M/s),文件2G以外(110M/s),bfin文件2G以内(750M/s),文件2G以外(110M/s)


=========================================================================================


byte[] b = new byte[8192];//缓冲区为8192个字节


文件复制速度:fin文件2G以内(830M/s),文件2G以外(110M/s),bfin文件2G以内(830M/s),文件2G以外(110M/s)


=========================================================================================


byte[] b = new byte[8192*10];//缓冲区为8192*10个字节


文件复制速度:fin文件2G以内(1365M/s),文件2G以外(110M/s),bfin文件2G以内(1365M/s),文件2G以外(110M/s)


=========================================================================================


byte[] b = new byte[8192*100];//缓冲区为8192*100个字节


文件复制速度:fin文件2G以内(1137M/s),文件2G以外(110M/s),bfin文件2G以内(1137M/s),文件2G以外(110M/s)


速度开始下降


=========================================================================================


byte[] b = new byte[8192*1000];//缓冲区为8192*1000个字节


文件复制速度:fin文件2G以内(751M/s),文件2G以外(110M/s),bfin文件2G以内(751M/s),文件2G以外(110M/s)


速度继续下降


===========================================================================================


总结:以指定缓存配合BufferedInputStream(其实缓存区超过8192字节时FileInputStream的速度也就一样了),选择合适长度字节。注意当指定的缓存区域过大或者待复制文件不能被缓存区整除是,复制的文件会造成扩大。




测试代码:


package day16;



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;


import java.nio.channels.FileChannel;



/**


* @author LPJ


* @version 1.0 创建时间:2018年1月1日 下午5:30:01


* describe:读取一个mp3文件,把此文件写入到new.mp3文件中,考虑到文件效率问题


*/


public class HW2_Copy {



public static void main(String[] args) {


FileInputStream fin,fin2;


BufferedInputStream bfin;


FileOutputStream fo,fo2;


BufferedOutputStream bfo;


try {


//--------------------------------------


File file = new File("d:/data/b.zip");


file.getName();


fin = new FileInputStream(file);


fo = new FileOutputStream("d:/data/b_1.zip");



int times = 0;


int count = 1;


int temp;



// while(fin.available() > 0) {//不指定缓冲区遍历输入


// fo.write(fin.read());


// while((temp = fin.read()) != -1) {//不指定缓冲区,不遍历输入


// fo.write(temp);


byte[] b = new byte[8192*1024];//缓冲区为1个字节


long d1 = System.currentTimeMillis();


// while((fin.read(b)) != -1) {


// fo.write(b);


// }


long d2 = System.currentTimeMillis();


System.out.println("复制完成,合计用时:" + (d2 - d1) / 1000.0 + "s");


//-----------------------------------------------------


File file2 = new File("d:/data/a.zip");


fin2 = new FileInputStream(file2);


bfin = new BufferedInputStream(fin2);


fo2 = new FileOutputStream("d:/data/a_1.zip");


bfo = new BufferedOutputStream(fo2);



times = 0;


count = 1;


long d3 = System.currentTimeMillis();


// while(bfin.available() > 0) {//不指定缓冲区


// bfo.write(bfin.read());


// while((temp = bfin.read()) != -1) {//不指定缓冲区,不遍历输入


// bfo.write(temp);


while((bfin.read(b)) != -1) {


bfo.write(b);


}


long d4 = System.currentTimeMillis();


System.out.println("buffer复制完成,合计用时:" + (d4 - d3) / 1000.0 + "s");


// ----方案1,速度高效286M 15S,不受内存大小限制速度18M/s


// while((tmp = bfin.read()) != -1) {


// bfo.write(tmp);


// ----方案2,速度慢,100M 150S,速度0.6M/s


// while(bfin.available() > 0) {


// bfo.write(bfin.read());


// -----方案3,与方案2速度一致


// while(bfin.available() > 0) {


// tmp = bfin.read();


// bfo.write(tmp);


// bfo.flush();严重影响速度


// ---方案4,速度最快


// 固定数值复制8912,10G数据1M43S,速度99M/s


// 固定数值复制8912 * 1024,10G数据a1M28S,速度116M/s


// 固定数值复制8912 * 8912,10G数据1M37S,速度105M/s


// 固定数值复制1024,10G数据1M47S,速度96M/s


// 固定数值复制10,10G数据2M32S,速度67M/s


// 固定数值复制1,10G数据10M6S,速度17M/s


// while((bfin.read(b)) != -1) {


// bfo.write(b);




try {


// in.close();


// out.close();


fo.close();


bfo.flush();


fin.close();



bfo.close();


bfin.close();


} catch (IOException e) {


e.printStackTrace();


}



} catch (FileNotFoundException e) {


e.printStackTrace();


} catch (IOException e) {


e.printStackTrace();


}


}


}