Posted on 2007-05-25 16:17
Computerboy 閱讀(2101)
評論(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){
}
}
}
}
而這個程序將其第一個參數中指定的文件復制到第二個參數所指定的文件中。
如果沒有第二個參數則復制到標準輸出。
同樣的方式,兩種實現,這就是我們所說的結果一樣,而過程也是千變萬化。
例二所涉及的包是我以前所沒有接觸到的。
歡迎朋友們來指正。