使用 java 进行文件拷贝
第一种方法:古老的方式
- public static long forJava(File f1,File f2) throws Exception{
- int length=2097152;
- FileInputStream in=new FileInputStream(f1);
- FileOutputStream out=new FileOutputStream(f2);
- byte[] buffer=newbyte[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中的管道到管道传输
- publicstaticlong 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();
- returnnew 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:内存文件景象写(读文件没有使用文件景象,有兴趣的可以回去试试,,我就不试了,估计会更快)
- publicstaticlong 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=newbyte[length];
- while(true){
- if(inC.position()==inC.size()){
- inC.close();
- outC.force();
- out.close();
- returnnew Date().getTime()-time;
- }
- if((inC.size()-inC.position())<length){
- length=(int)(inC.size()-inC.position());
- }else{
- length=20971520;
- }
- b=newbyte[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种方法:管道对管道
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();
- returnnew 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);
- }
- }
解释: 在测试结果中看到 古老方式,和管道向管道传输是最快的,,,,,为什么呢?
我分析是这样的,由于另外2种方法内部都使用了 字节数组作为缓存中转,在加上NIO内部有一个贴近系统的缓存区,这无意就增加了另一个缓存器,所以相对于这2个方法就要慢许多,,如果不使用 字节数组作为数据中转的话相信速度会更快的..