1. 程式人生 > >java 7新特性-TWR(Try-with-resources)

java 7新特性-TWR(Try-with-resources)

今天在資料上練習檔案拷貝程式時,遇到了java 7中的一個新特性TWR,可以減少實際中的部分程式碼書寫,對其做以記錄。

try-with-resources語句是聲明瞭一個或多個資源的try語句塊。在java中資源作為一個物件,在程式完成後必須關閉。try-with-resources語句確保每個資源在語句結束時關閉。只要是實現了java.lang.AutoCloseable的任何物件(包括實現java.lang.Closeable的所有物件)都可以使用該方式對資源進行關閉。

在java 7之前,一般在進行檔案IO操作時都需要顯式的進行檔案流(也可以理解為資源)的close操作,無論是操作到檔案流末尾還是發生異常。往往很簡單的一個邏輯都要好幾行的程式碼進行修飾,使得程式碼結構變的複雜。如下例子,不管try語句塊正常結束還是發生異常,都可以使用finally語句塊來確保資源被關閉:

static String ReadFile(String file) throws IOException {
  BufferedReader br = new BufferedReader(new FileReader(file));
  try {
    return br.readLine();
  } finally {
    if (br != null) 
         br.close();
  }
}

對於以上語句塊,改寫為TWR時,如下:

static String ReadFile(String file) throws IOException {
  try(BufferedReader br = new BufferedReader(new FileReader(file))) {
    return br.readLine();
  }
}
可以很明顯看出程式碼的精簡。

上邊說過,只要是實現了AutoCloseable和Closeable介面的的物件都可以使用該方式,看下上例子中的BufferedReader類的原始碼實現:

public class BufferedReader extends Reader {
其繼承了Reader抽象類,繼續往上檢視Reader抽象類,確實實現了Closeable:
public abstract class Reader implements Readable, Closeable {

明白了TWR具體含義,例項運用下,實現檔案拷貝實現,程式碼中採用了兩種方式實現檔案拷貝過程(普通方式和NIO方式),兩者存在一些效能的差異,感興趣的讀者可以自己測試程式碼效能。
package javaFile.copyfile;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public final class CopyFile {     //使用final定義工具類,不用例項化
	private CopyFile() {   //若例項化,則報錯
		throw new AssertionError();
	}
	
	public static void fileCopy(String source, String target) throws IOException {
		try(InputStream in = new FileInputStream(source)) {
			try(OutputStream out = new FileOutputStream(target)){
				byte[] buffer = new byte[4096];
				int bytesToRead;
				while((bytesToRead = in.read(buffer)) != -1) {
					out.write(buffer, 0, bytesToRead);
				}
			}
		}
	}
	
	public static void fileCopyNIO(String source, String target) throws IOException {
		try(FileInputStream in = new FileInputStream(source)) {
			try(FileOutputStream out = new FileOutputStream(target)) {
				FileChannel inChannel = in.getChannel();
				FileChannel outChannel = out.getChannel();
				ByteBuffer buffer = ByteBuffer.allocate(4096);  //申請4096位元組緩衝
				while(inChannel.read(buffer) != -1) {
					buffer.flip();   //反轉此緩衝區,設定當前位置指標為0,read讀檔案後文件指標在緩衝區末尾,需要使用flip重置
					outChannel.write(buffer);
					buffer.clear();   //清空緩衝區
				}
			}
		}
	}
	
	public static void main(String[] args) throws IOException {
		//CopyFile copyfile = new CopyFile();
		long start = System.currentTimeMillis();
		CopyFile.fileCopyNIO("E:\\大資料.rar", "E:\\testtest");
		long end = System.currentTimeMillis();
		System.out.println("耗時:"+(end-start));
	}
}