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,加油。接口