Posted on 2007-05-25 16:17
Computerboy 阅读(2087)
评论(4) 编辑 收藏 所属分类:
编程技术
一个文件的复制我们大概的思维是通过流来操作,不错。
本文也是这样操作的。
至于第一种方法是我们一般的操作方式,而第二种方法其实也是一个方式,我们不妨研究一下。
闲话少说。看程序。
这个程序我写的是两个方法,支持从命令行操作。
例一:
package org.stonecn.kernel;
import java.io.*;
public class FileCopy {
/**
* 测试程序
*/
public static void main(String[] args){
if(args.length!=2)
System.err.println("Usage: java FileCopy<source><destination>");
else{
try{
copy(args[0],args[1]);
}
catch(IOException e){
System.err.println(e.getMessage());
}
}
}
public static void copy(String from_name,String to_name)throws IOException{
File from_file=new File(from_name);
File to_file=new File(to_name);
if(!from_file.exists())
abort("no such source file:"+from_name);
if(!from_file.isFile())
abort("can't copy directory:"+from_name);
if(!from_file.canRead())
abort("source file is unreadable:"+from_name);
/**
* 如果目标是一个目录,则使用源文件名作为目标文件名
*/
if(to_file.isDirectory())
to_file=new File(to_file,from_file.getName());
/**
* 如果目标文件存在,则确保它是可写的,并且在覆盖之前先询问
* 如果目标文件不存在,则确保存在目录,而且是可写的。
*/
// 此处支持命令行,如果不用可以注视掉。 sart
if(to_file.exists()){
abort("destination file is unwriteable:"+to_name);
//询问是否覆盖
System.out.print("Overwrite existing file:"+to_file.getName()+"?(Y/N):");
//得到用户响应
System.out.flush();
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
String response=in.readLine();
//检查响应,如果不是yes(未做确认),则终止复制
if(!response.equals("Y") && !response.equals("y"))
abort("existing file was not overwritten.");
}
else{
/**如果文件不存在,检查是否存在目录且是否可写
* 如果getParent()返回null,则目录就是当前dir,
* 因此查找user.dir系统特性,以得出它是什么
*/
String parent=to_file.getParent(); //目标目录
if(parent == null)
parent=System.getProperty("user.dir");
File dir=new File(parent);
if(!dir.exists())
abort("destination directory doesn't exist:"+parent);
if(dir.isFile())
abort("destination is not a directory:"+parent);
if(!dir.canWrite())
abort("destination directory is unwriteable:"+parent);
}
//到此结束 end
/**
* 如果走到这了,则一切正常。
* 因此可以复制文件,一次复制一个字节缓冲区
*/
FileInputStream from=null; //从源读取的流
FileOutputStream to=null; //写至目标的流
try{
from=new FileInputStream(from_file); //创建输入流
to=new FileOutputStream(to_file); //创建输出流
byte[] buffer=new byte[4096];
int bytes_read;
/**
* 将一块字节读入缓冲区,然后将其写出
* 如果循环,知道达到文件结束(read()返回-1)
* 注意,在此while循环中结合了赋值和比较
*/
while((bytes_read=from.read(buffer))!=-1) //读,直到EOF
to.write(buffer,0,bytes_read); //写
}
finally{
if(from!=null)
try{
from.close();
}
catch(IOException e){
;
}
if(to!=null)
try{
to.close();
}
catch(IOException e){;}
}
}
/**
* 这是抛出异常的一个便利方法
*/
private static void abort(String msg)throws IOException{
throw new IOException("FileCopy:"+msg);
}
}
这个程序的好处是一个安全的。因为有一个静态的copy方法。其他程序也可以使用此方法来复制文件
我们来看第二个例子
例二:
package org.stonecn.kernel;
import java.io.*;
import java.nio.channels.*;
public class FileCopy2{
public static void main(String[] args){
FileInputStream fin=null; //两个文件的流
FileOutputStream fout=null; //这些流要在finally块中关闭
try{
//打开输入文件的一个流,并从中得到一个通道
fin=new FileInputStream(args[0]);
FileChannel in=fin.getChannel();
//下面得到输出通道
WritableByteChannel out;
//如果有第二个文件名
if(args.length>1){
fout=new FileOutputStream(args[1]);
out=fout.getChannel();
}
else{
//没有目标文件名
out=Channels.newChannel(System.out); //包装stdout流
}
//查询输入文件的大小
long numbytes=in.size();
/**
*采用批量传输的方式将所有字节从一个通道传输到另一个通道
*这是fileChannel通道的一个特殊特性
*参见FileChannel.transferForm()
*/
in.transferTo(0,numbytes,out);
}
catch(IOException e){
System.out.println(e);
}
finally{
try{
if(fin!=null) fin.close();
if(fout!=null) fout.close();
}
catch(IOException e){
}
}
}
}
而这个程序将其第一个参数中指定的文件复制到第二个参数所指定的文件中。
如果没有第二个参数则复制到标准输出。
同样的方式,两种实现,这就是我们所说的结果一样,而过程也是千变万化。
例二所涉及的包是我以前所没有接触到的。
欢迎朋友们来指正。