java 7新特性-TWR(Try-with-resources)
阿新 • • 發佈:2019-01-02
今天在資料上練習檔案拷貝程式時,遇到了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)); } }