JavaIO流中的拷貝

  JavaIO流中對數據的操做尤其重要,掌握了基本的拷貝操做,才能將各類數據源的操做聯繫起來。ios

  先來看看對文件夾的拷貝吧:數組

 1 /**
 2  * 利用遞歸實現文件夾的拷貝操做
 3  * 分析:判斷
 4  *     是文件:調用拷貝文件的方法fileCopy(...)
 5  *     是文件夾:建立文件夾,並使用遞歸實現子文件夾/子文件的判斷及操做
 6  * @param src:要拷貝的文件夾源頭
 7  * @param dest:要拷貝到的文件夾源頭
 8  */
 9 public static void dirCopy(File src,File dest) {
10     if(src.isFile()) { //是文件
11         fileCopy(src, dest);
12     }else { //是文件夾
13         dest.mkdirs();
14         for(File subSrc:src.listFiles()) { //遍歷子文件夾/子文件
15             dirCopy(subSrc, new File(dest,subSrc.getName()));
16         }
17     }
18 }

  對文件的拷貝,咱們能夠這樣寫:spa

 1 /**
 2  * 實現文件的拷貝
 3  *     輸入流讀取的同時輸出流進行寫出
 4  * @param src:要拷貝的文件源頭
 5  * @param dest:要拷貝到的文件源頭
 6  */
 7 public static void fileCopy(File src,File dest) {
 8     //1.建立源
 9     //2.選擇流
10     InputStream is = null;
11     OutputStream os = null;
12     try {
13         is = new FileInputStream(src);
14         os = new FileOutputStream(dest);
15         //3.操做:分段讀取並寫出
16         int len; //接收長度
17         byte[] flush = new byte[1024]; //緩衝容器,一次讀寫1k
18         while((len=is.read(flush))!=-1) {
19             os.write(flush, 0, len);
20         }
21         os.flush(); //寫完手動刷新,避免數據在緩衝容器中(固然當流關閉時會自動刷新)
22     }catch(FileNotFoundException e) {
23         e.printStackTrace();
24     }catch(IOException e) {
25         e.printStackTrace();
26     }finally {
27         //4.關閉流,分別關閉,先打開的後關閉
28         try {
29             if(os!=null) {    //判斷是否爲空,避免空指針異常
30                 os.close();
31             }
32         }catch(IOException e) {
33             e.printStackTrace();
34         }
35         try {
36             if(is!=null) { //判斷是否爲空,避免空指針異常
37                 is.close();
38             }
39         }catch(IOException e) {
40             e.printStackTrace();
41         }
42     }
43 }

  以上代碼只能實現對文件的拷貝操做,固然適合於拷貝任何格式的數據文件,包括視頻、音頻、圖片等等。可是若是我想將一張圖片拷貝到字節數組中呢(這裏的字節數組至關於內存),也就是說從文件到字節數組,或着是從字節數組到文件。那麼以上代碼就具備侷限性了,也不易於擴展,來看如下代碼:指針

 1 /**
 2  * 對接流
 3  * @param is:輸入流
 4  * @param os:輸出流
 5  */
 6 public static void copy(InputStream is,OutputStream os) {
 7     //1.建立源
 8     //2.選擇流
 9     try {
10         //3.操做
11         byte[] flush = new byte[1024]; //緩衝容器
12         int len; //接收長度
13         while((len=is.read(flush))!=-1) {
14             os.write(flush, 0, len);
15         }
16         os.flush();
17     }catch(FileNotFoundException e) {
18         e.printStackTrace();
19     }catch(IOException e) {
20         e.printStackTrace();
21     }finally {
22         try {
23             if(os!=null) {
24                 os.close();
25             }
26         }catch(IOException e) {
27             e.printStackTrace();
28         }
29         try {
30             if(is!=null) {
31                 is.close();
32             }
33         }catch(IOException e) {
34             e.printStackTrace();
35         }
36     }
37 }

  嗯,這樣就能夠實現以上要求了,可是咱們發現:關閉資源的操做一直在,並且都同樣,咱們能夠封裝一下,這樣在finally中就能夠直接調用了。code

 1 /**
 2  * 關閉的方法
 3  * @param is:輸入流
 4  * @param os:輸出流
 5  */
 6 public static void close(InputStream is,OutputStream os) {
 7     try {
 8         if(os!=null) {
 9             os.close();
10         }
11     }catch(IOException e) {
12         e.printStackTrace();
13     }
14     try {
15         if(is!=null) {
16             is.close();
17         }
18     }catch(IOException e) {
19         e.printStackTrace();
20     }
21 }

  好了,看看封裝的代碼,幸好只有兩個流,要是流不少咋辦,形參太多,可是咱們發現輸入流InputStream和輸出流OutputStream都實現了同一個接口:Closeable。嗯,這樣,咱們能夠試試JDK1.5的新特性:可變參數。視頻

 1 /**
 2  * 封裝的關閉方法
 3  * @param ios:要關閉的流
 4  */
 5 public static void close(Closeable... ios) {
 6     for(Closeable io:ios) {
 7         try {
 8             if(io!=null) {
 9                 io.close();
10             }
11         }catch(IOException e) {
12             e.printStackTrace();
13         }
14     }
15 }

  如今看似完美了,但我還不太滿意,有時候,我以爲手動關閉資源太麻煩了。別急,來看看JDK1.7的新特性:try...with...resources(自動關閉資源)。blog

 1 /**
 2  * JDK1.7以後的新特性 try...with...resources:自動關閉資源
 3  * 文件的拷貝
 4  * @param srcPath:要拷貝的源頭
 5  * @param destPath:要拷貝到的目的地
 6  */
 7 public static void copy1(String srcPath,String destPath) {
 8     //1.建立源
 9     File src = new File(srcPath);
10     File dest = new File(destPath);
11     //2.選擇流
12     try(InputStream is = new FileInputStream(src);
13         OutputStream os = new FileOutputStream(dest)) {
14         //3.操做
15         byte[] flush = new byte[1024]; //緩衝容器
16         int len; //接收長度
17         while((len=is.read(flush))!=-1) {
18             os.write(flush, 0, len);
19         }
20         os.flush();
21     }catch(FileNotFoundException e) {
22         e.printStackTrace();
23     }catch(IOException e) {
24         e.printStackTrace();
25     }
26 }

  你們發現:try裏面寫的好繁瑣,別急,看看JDK1.9的改進版(不過要求你所要關閉的資源是final或等效於final的變量)。遞歸

 1 /**
 2  * JDK1.9以後對 try...with...resources的改進
 3  * 對接流
 4  * @param is:輸入流
 5  * @param os:輸出流
 6  */
 7 public static void copy2(InputStream is,OutputStream os) {
 8     //1.建立源
 9     //2.選擇流
10     try(is;os) {
11         //3.操做
12         byte[] flush = new byte[1024]; //緩衝容器
13         int len; //接收長度
14         while((len=is.read(flush))!=-1) {
15             os.write(flush, 0, len);
16         }
17         os.flush();
18     }catch(FileNotFoundException e) {
19         e.printStackTrace();
20     }catch(IOException e) {
21         e.printStackTrace();
22     }
23 }

  哈哈,看上去是否是簡潔不少。對的,隨着JDK的新版本發佈,愈來愈多的新技術,也使得代碼看起來越簡潔,不過對咱們的要求也只會愈來愈高。前段時間JDK12已經出來了,還沒用,不過我相信確定會有好多的新特性,期待,也看好Java,加油。接口

相關文章
相關標籤/搜索