开发者学堂课程【Java 高级编程:综合实战:文件拷贝】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/20/detail/318
综合实战:文件拷贝
内容简介:
一 、实现文件拷贝处理
二、使用转存的方式处理
一 、实现文件拷贝处理
在操作系统里面有一个 copy 命令,这个命令的主要功能是可以实现文件的拷贝处理。
现在要求模拟这个命令,通过初始化参数输入拷贝的源文件路径与拷贝的目标路径,实现文件的拷贝处理。
以下为需求分析:
需要实现文件的拷贝操作,那么这种拷贝就有可能拷贝各种类型的文件,所以此时选择使用字节流。
在进行拷贝的时候,有可能需要考虑到大文件的拷贝问题。
实现方案如下:
方案一:使用 input stream 将全部要拷贝的内容直接读取到程序里面,而后一次性的输出到目标文件;此方案的缺点就在于,如果现在拷贝的文件很大,基本上程序就死了;
方案二:采用部分拷贝,读取一部分输出一部分数据,如果现在要采用第二种做法,核心的操作方法为 Input stream 和 output stream。
主要用的是 input stream 中的以下方法:
Public int read(byte[]b)
Throws IOException
Output stream 中的是以下方法:
Public void write(byte[]b),
Int off,
Int len)
Throws IOException
范例:实现文件拷贝处理
需要两个文件路径,一是原文件路径,另外一个是目标文件路径。
在进行文件拷贝处理的时候,应该传入源文件路径和目标文件路径。接下来主要执行拷贝处理。
初始化参数,如果不等于初始化参数,程序执行错误,可以退出。最后再加上拷贝完成的时间,保证源文件必须存在,如果源文件不存在可以返回,直接拷贝失败。
创建父目录,实现拷贝。先开辟一个拷贝的缓冲区,文件是一个重要的资源。
最后无论是否成功,都要关闭文件。并且在代码中不能用 io ,io 太小了,会发生异常。还存在一个长度问题,因为存在文件太大的问题。拷贝的内容都在 data 数组里,代码可以执行输出 data。但是存在读不满的情况,所以最好输出零到部分。
还需要进行判断,定义文件路径后程序才能正常运行,文件拷贝才会成功。
package cn.mldn.demo;
import java.io.File;
import java.io.FileInputStream;7
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
class FileUtil {//定义一个文件操作的工具类
private File srcFile;//源文件路径
private File desFile;//目标文件路径
public FileUtil(String src,String des) {
this(new File(src),new File(des));
}
public FileUtil(File srcFile,File desFile){
this.srcFile = srcFile ;
this.desFile = desFile:
文件拷贝处理
public boolean copv() throws Exception { //文件拷贝处理
if(!this.scrFile.exists()){ //源文件必须存在
System.out..println(拷贝的源文件不存在!);
Return false; //拷贝失败
}
if (!this.desFile.getParentFile().exists()) {
this.desFile.getParentFile().mkdirs();//创建父目录
byte data []=new byte[1024];//开辟一个拷贝的缓冲区
InputStream input = null ;
OutputStream output = null ;
try{
input = new FileInputStream(this.srcFile) ;
output = new FileOutputStream(this.desFile);
int len = 0;
do {
len=input.read(data);//拷贝的内容都在data数组
output.write(data, 0, len);
} while (len != -1);
return true ;
} catch (Exception e){
throw e;} finally{
if(input != null){
input.close();
}
if(output != null)(
output.close();
}
}
}
public class JavaAPIDemo {
public static void main(String[] args)throws Exception
{
if(args.length I= 2){
//程序执行出備
System.out.println(“命令执行错误,执行锚构:Java
JavaAPIDemo拷贝源文件路径排贝目标文件路径”);
System.exit(1);
long start = Systél.currentTimeMillis();
FileUtil fu =new FileUtil(args[0],args[1]) ;
System.out.println(fu.copy()?“文件拷贝成功!":
“文件拷贝失败!“);
long end = System.currentTimeMillis() ;
System.out.println(”拷贝完成的时间:“+(end-start));
}
}
这类代码存在两个好处。
1.读取数据到数组之中,随后返回读取的个数;
2.判断个数是否是-1,如果不是,则进行写入。
While((len = inpit read(data))!=-1){
Output.write(data,0,len);
}
但是需要注意的是,以上的做法是属于文件拷贝的最原始实现,而从 jdk1.9 开始,inputstream 和 reader 类中都追加有数据转存的处理操作方法:
Reader:public long transferTo(Writer out)throws IOException
Public long transferTo(OutputStream out)throws
IOExceptiom
二、使用转存的方式处理
范例:使用转存的方式处理
有了 transfer to 后传统代码中的以下代码不需要使用
更改为以下内容
Input transferTo(output);
Return true;
}catch(Exception e){
省略之后,也不需要开辟数组且效率大幅提升。但用此程序之前,需考虑好版本。如果说现在对此程序要求进一步扩展,可以实现一个文件目录的拷贝。一旦进行了文件目录的拷贝,还需要拷贝所有的子目录中的文件。
如果需要传送两个目录,代码需要发生一定变化。程序应该具备检测目录或内容的功能。拷贝的处理将发生变化,变化如下
if(new File(angs[e]).isFile())( / mleg
System.out.println(fu.copy()?“文件持贝成功!“:“文件拷贝失败!“);}else{ //目录拷贝
System.out.println(fu.copyDrk) ?“文件持贝成功!“:“文件拷贝失败!“);
}
目录拷贝中应该存在一个单独的方法,结构需要发生变化。内部拷贝需要实现就需要传入源文件路径和目标文件路径。
prlvate void copyFileImpl(File srcFile,File desFile){
InputStream input = null ;
OutputStream output = null;
try{
input w new FileInputStream(this.srcFile);
output=newFileOutputStream(this.desFile);input.transferTo(output);
return true;
} catch (Exception e){
throw e ;
}finally {
if (input I= nul1)
input.close();
}
if(output I= nul1){
output.close();
}
}
其中,不能用 this 来完成,要用传入的两个路径来完成。此处为专门做拷贝。需要进行递归操作。
publicFileUtil(File srcFile,File desFile)(this.srcFile srcFilethis.desFile = desFile;
public boolean copyDir()throws Exception{this.copyImpl(smcFile, desFile)return false;
private void copyImpl(File file)throws Exception{//1f (file.isDirectory())( _
File results [] = file.1istFiles();// Fif (results I= null)(for (int x e;
x ( results.length;x++){
copyImpl(results[×]);
} else {
//是文件
String neaFilepath w file.getPath().replace(this.srcFile.getPath()+ File.separator,"")
File neuFile s new File(this.desFile,newFilePath);
}
}
拥有原始路径后调用 copy file,就可以实现拷贝处理。
以上为文件夹拷贝,其重点就在于执行递归处理操作而后实现处理过程。
本程序是 io 操作的核心代码。