读书人

Java实现文件拷贝的4种方法

发布时间: 2013-01-25 15:55:29 作者: rapoo

Java实现文件拷贝的4种方法.
public static long forJava(File f1,File f2) throws Exception{ long time=new Date().getTime(); int length=2097152; FileInputStream in=new FileInputStream(f1); FileOutputStream out=new FileOutputStream(f2); byte[] buffer=new byte[length]; while(true){ int ins=in.read(buffer); if(ins==-1){ in.close(); out.flush(); out.close(); return new Date().getTime()-time; }else out.write(buffer,0,ins); } }

?

方法的2参数分别是原始文件,和拷贝的目的文件.这里不做过多介绍.

实现方法很简单,分别对2个文件构建输入输出流,并且使用一个字节数组作为我们内存的缓存器, 然后使用流从f1 中读出数据到缓存里,在将缓存数据写到f2里面去.这里的缓存是2MB的字节数组

第2种方法:使用NIO中的管道到管道传输

 public static long forTransfer(File f1,File f2) throws Exception{        long time=new Date().getTime();        int length=2097152;        FileInputStream in=new FileInputStream(f1);        FileOutputStream out=new FileOutputStream(f2);        FileChannel inC=in.getChannel();        FileChannel outC=out.getChannel();        int i=0;        while(true){            if(inC.position()==inC.size()){                inC.close();                outC.close();                return new Date().getTime()-time;            }            if((inC.size()-inC.position())<20971520)                length=(int)(inC.size()-inC.position());            else                length=20971520;            inC.transferTo(inC.position(),length,outC);            inC.position(inC.position()+length);            i++;        }    }

?

实现方法:在第一种实现方法基础上对输入输出流获得其管道,然后分批次的从f1的管道中像f2的管道中输入数据每次输入的数据最大为2MB

方法3:内存文件景象写(读文件没有使用文件景象,有兴趣的可以回去试试,,我就不试了,估计会更快)

    public static long forImage(File f1,File f2) throws Exception{        long time=new Date().getTime();        int length=2097152;        FileInputStream in=new FileInputStream(f1);        RandomAccessFile out=new RandomAccessFile(f2,"rw");        FileChannel inC=in.getChannel();        MappedByteBuffer outC=null;        MappedByteBuffer inbuffer=null;        byte[] b=new byte[length];        while(true){            if(inC.position()==inC.size()){                inC.close();                outC.force();                out.close();                return new Date().getTime()-time;            }            if((inC.size()-inC.position())<length){                length=(int)(inC.size()-inC.position());            }else{                length=20971520;            }            b=new byte[length];            inbuffer=inC.map(MapMode.READ_ONLY,inC.position(),length);            inbuffer.load();            inbuffer.get(b);            outC=out.getChannel().map(MapMode.READ_WRITE,inC.position(),length);            inC.position(b.length+inC.position());            outC.put(b);            outC.force();        }    }

?

?

实现方法:跟伤2个例子不一样,这里写文件流没有使用管道而是使用内存文件映射(假设文件f2在内存中).在循环中从f1的管道中读取数据到字节数组里,然后在像内存映射的f2文件中写数据.

第4种方法:管道对管道

这里实现方式与第3种实现方式很类似,不过没有使用内存影射.

?

    public static long forChannel(File f1,File f2) throws Exception{        long time=new Date().getTime();        int length=2097152;        FileInputStream in=new FileInputStream(f1);        FileOutputStream out=new FileOutputStream(f2);        FileChannel inC=in.getChannel();        FileChannel outC=out.getChannel();        ByteBuffer b=null;        while(true){            if(inC.position()==inC.size()){                inC.close();                outC.close();                return new Date().getTime()-time;            }            if((inC.size()-inC.position())<length){                length=(int)(inC.size()-inC.position());            }else                length=2097152;            b=ByteBuffer.allocateDirect(length);            inC.read(b);            b.flip();            outC.write(b);            outC.force(false);        }    }

?

下面是对49.3MB的文件进行拷贝的测试时间(毫秒)

Start Copy File...? file size:50290KB
CopyFile:b1.rmvb?mode:forChannel??RunTime:3203
CopyFile:b1.rmvb?mode:forImage??RunTime:3328
CopyFile:b1.rmvb?mode:forJava??RunTime:2172
CopyFile:b1.rmvb?mode:forTransfer?RunTime:1406
End Copy File!

解释: 在测试结果中看到 古老方式,和管道向管道传输是最快的,,,,,为什么呢?

我分析是这样的,由于另外2种方法内部都使用了 字节数组作为缓存中转,在加上NIO内部有一个贴近系统的缓存区,这无意就增加了另一个缓存器,所以相对于这2个方法就要慢许多,,如果不使用 字节数组作为数据中转的话相信速度会更快的..

不过比较惊讶的是 管道向管道传输的速度还是真挺吓人,,,?

我的机器是 IDE硬盘120G 硬盘缓存2MB, 内存1GB, CPU AMD2800+

读书人网 >编程

热点推荐