Java文件操作
1 Java文件操作之文件复制
Java中实现文件复制一共有四种方法,方法不同,自然效率也不同。
1.1 第一种方法:原始方式
1 import java.io.*;//需要导入IO类 2 /***下面的只是一个方法***/ 3 public static long forJava(File f1,File f2) throws Exception{//定义文件复制方法 4 int length=2097152;//定义字节大小,大小为2M 5 FileInputStream in=new FileInputStream(f1);//由f1创建一个输入流 6 FileOutputStream out=new FileOutputStream(f2);//由f2创建一个输出流 7 byte[] buffer=new byte[length];//定义字节数组 8 while(true){//进入死循环 9 int ins=in.read(buffer);//将f1代表的文件读到数组中,并获取长度 10 if(ins==-1){//如果文件大小不存在 11 in.close();//关闭输入流 12 out.flush();//彻底完成输出,并清空缓存区 13 out.close();//关闭输出流 14 }else//否则 15 out.write(buffer,0,ins);//将数组中的内容写到输出流 16 } 17 }
此为不完整代码,只定义一个方法,用的时候直接调用即可。这种方法实现较为简单,分别对两个文件构造输入输出流,并使用一个字节数组作为缓存器,然后使用流从文件f1中读取数据到缓存器,缓存器能存储的最大文件大小为2M,再把缓存器中的内容写到目标文件f2中。
1.2 第二种方法:使用NIO中的管道传输
1 import java.io.*;//导入文件类 2 import java.nio.channels.FileChannel;//需要导入NIO类 3 /***下面的只是一个方法***/ 4 public static long forTransfer(File f1,File f2) throws Exception{ 5 int length=2097152; 6 FileInputStream in=new FileInputStream(f1); 7 FileOutputStream out=new FileOutputStream(f2); 8 FileChannel inC=in.getChannel(); 9 FileChannel outC=out.getChannel(); 10 while(true){ 11 if(inC.position()==inC.size()){ 12 in.close(); 13 out.close(); 14 inC.close(); 15 outC.close(); 16 } 17 if((inC.size()-inC.position())<20971520) 18 length=(int)(inC.size()-inC.position()); 19 else 20 length=20971520; 21 inC.transferTo(inC.position(),length,outC); 22 inC.position(inC.position()+length); 23 } 24 }
此种方法主要是在第一种方法的基础上对输入输出流获得其管道,然后分批次的从f1的管道中向f2的管道中输入数据,每次输入的数据最大为2M。
1.3 第三种方法:内存文件镜像
1 import java.io.*;//导入文件类 2 import java.nio.MappedByteBuffer; 3 import java.nio.channels.FileChannel; 4 import java.nio.channels.FileChannel.MapMode; 5 /***下面的只是一个方法***/ 6 public static long forImage(File f1,File f2) throws Exception{ 7 int length=2097152; 8 FileInputStream in=new FileInputStream(f1); 9 RandomAccessFile out=new RandomAccessFile(f2,"rw"); 10 FileChannel inC=in.getChannel(); 11 MappedByteBuffer outC=null; 12 MappedByteBuffer inbuffer=null; 13 byte[] b=new byte[length]; 14 while(true){ 15 if(inC.position()==inC.size()){ 16 in.close(); 17 out.close(); 18 inC.close(); 19 outC.force(); 20 } 21 if((inC.size()-inC.position())<length){ 22 length=(int)(inC.size()-inC.position()); 23 }else{ 24 length=20971520; 25 } 26 b=new byte[length]; 27 inbuffer=inC.map(MapMode.READ_ONLY,inC.position(),length); 28 inbuffer.load(); 29 inbuffer.get(b); 30 outC=out.getChannel().map(MapMode.READ_WRITE,inC.position(),length); 31 inC.position(b.length+inC.position()); 32 outC.put(b); 33 outC.force(); 34 } 35 }
此方法写文件流中没有用到管道,而是使用内存文件映射(假设文件f2在内存中),在循环中从f1的管道中读取数据到字节数组中,然后再向内存映射f2文件中写数据。
1.4 第四种方法:管道对管道
1 import java.io.*;//导入文件类 2 import java.nio.ByteBuffer; 3 import java.nio.channels.FileChannel; 4 /***下面的只是一个方法***/ 5 public static long forChannel(File f1,File f2) throws Exception{ 6 int length=2097152; 7 FileInputStream in=new FileInputStream(f1); 8 FileOutputStream out=new FileOutputStream(f2); 9 FileChannel inC=in.getChannel(); 10 FileChannel outC=out.getChannel(); 11 ByteBuffer b=null; 12 while(true){ 13 if(inC.position()==inC.size()){ 14 in.close(); 15 out.close(); 16 inC.close(); 17 outC.close(); 18 } 19 if((inC.size()-inC.position())<length){ 20 length=(int)(inC.size()-inC.position()); 21 }else 22 length=2097152; 23 b=ByteBuffer.allocateDirect(length); 24 inC.read(b); 25 b.flip(); 26 outC.write(b); 27 outC.force(false); 28 } 29 }
该方法和第三种方法相似,不过没有使用内存映射。
1.5 总结
如果利用时间类获取程序运行的时间,可以发现,对于同一个文件,第一种方法和第四种方法是运行速度最快的,尤其是第四种方法。原因可能是另外两种方法中都有字节数组作为缓存器,再加上NIO内部有一个贴近系统的缓存器,这无疑相当于两个缓存器了,所以相对就慢很多。
【注】以上部分来源于 Java实现文件拷贝的4种方法,经本人稍作修改。
2 Java文件操作之文件移动
移动文件到指定目录,并不是复制后再删除源文件,而是使用renameTO方法实现。
1 import java.io.File;//导入文件类 2 public class GCXL21K3 {//主类 3 public static void main(String[] args) {//主方法 4 try {//异常处理 5 File afile = new File("E:\\word.txt");//创建文件对象 6 if(afile.renameTo(new File("D:\\" + afile.getName()))){//执行复制命令 7 System.out.println("File is moved successful!");//输出成功 8 }else{//否则 9 System.out.println("File is failed to move!");//输出失败 10 } 11 }catch(Exception e){//异常处理 12 e.printStackTrace();//输出异常信息 13 } 14 } 15 }
在JDK手册中,这样介绍renameTO方法:
renameTO(File dast) 重新命名此抽象路径名表示的文件
作者:祁俊辉
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。