前言
本文将上一节做的代码,对copy方法与关闭流方法进行封装,并使用try...with...resource关闭流。
copy方法封装
我们将copy方法封装,使得只需传入两个流,就能将输入流的源文件copy到输出流的目的文件。
值得注意的是,由于ByteArrayOutputStream不能直接写入文件,调用此方法后,数据保存在流中。
流关闭方法封装
方法一:原始方法
最原始的方法莫过于try...catch与close()结合
public static void close(InputStream is,OutputStream os){ try{ if(null!=os){ os.close(); } }catch(IOException e){ e.printStackTrace(); } try{ if(null!=is){ is.close(); } }catch(IOException e){ e.printStackTrace(); } }
方法二:多流关闭
使用方法的可变参数,通过遍历的方法,一个个关闭流。
public static void close(Closeable...ios){ for(Closeable io : ios){ try{ io.close(); }catch(IOException e){ e.printStackTrace(); } } }
方法三:try...with...resource语法糖
在jdk1.7开始,就可以使用try...with...resource方法进行处理那些实现了Autocloseable的类或对象。它的格式是:
try(xxx cc = new xxx()){
}catch(...){...}
public static void copy2(String filePath,String destPath){ //操作流 try(InputStream is = new FileInputStream(filePath); OutputStream os = new FileOutputStream(destPath)){//没有先后顺序 byte[] flush = new byte[1024*10];//缓冲池 int len = -1;//接收单次读取的长度 while((len = is.read(flush))!=-1){//读取数据 os.write(flush,0,len);//写入数据 } os.flush();//刷新 }catch(IOException e){ e.printStackTrace(); }//这里无需关闭方法 }
写在try后的小括号中,如果有多个,用英文分号分隔。在括号中写完整的流声明,在执行完try后将自动关闭流。
在jdk1.9中进行了升级:可以不用xxx cc =new xxx()的方式,而是直接传入对象即可,格式为:
try(object1;object2...){..}catch(...){...}
同样可以传多个对象。
public static void copy2(String filePath,String destPath){ //操作流 try(is;os){//没有先后顺序 byte[] flush = new byte[1024*10];//缓冲池 int len = -1;//接收单次读取的长度 while((len = is.read(flush))!=-1){//读取数据 os.write(flush,0,len);//写入数据 } os.flush();//刷新 }catch(IOException e){ e.printStackTrace(); }//这里无需关闭方法 }
关于本文的完整练习代码
import java.io.*; public class IOTest02 { public static void main(String[] args){ byte[] datas =null; //文件到文件 try{ InputStream is = new FileInputStream("1.png"); OutputStream os = new FileOutputStream("1_copy.png"); copy(is,os); }catch(FileNotFoundException e){ e.printStackTrace(); } //文件到字节数组 try{ InputStream is = new FileInputStream("1.png"); ByteArrayOutputStream fos = new ByteArrayOutputStream(); copy(is,fos); datas = fos.toByteArray(); System.out.println("copy到的数据大小:"+datas.length); }catch(IOException e){ e.printStackTrace(); } //字节数组到文件 try{ InputStream is = new ByteArrayInputStream(datas); OutputStream os = new FileOutputStream("2_copy.png"); copy(is,os); }catch(IOException e){ e.printStackTrace(); } //测试copy2方法 String filePath = "3.png"; String destPath = "3-copy.png"; copy2(filePath,destPath); } /** *封装拷贝方法 */ public static void copy(InputStream is,OutputStream os){ //操作流 try{ byte[] flush = new byte[1024*10];//缓冲池 int len = -1;//接收单次读取的长度 while((len = is.read(flush))!=-1){//读取数据 os.write(flush,0,len);//写入数据 } os.flush();//刷新 }catch(IOException e){ e.printStackTrace(); }finally{ //调用关闭流 close2(is,os); //或close()两个方法都可以 } } /** *封装关闭流方法1:最原始的方法 */ public static void close(InputStream is,OutputStream os){ try{ if(null!=os){ os.close(); } }catch(IOException e){ e.printStackTrace(); } try{ if(null!=is){ is.close(); } }catch(IOException e){ e.printStackTrace(); } } /** *封装关闭方法2:可变参数关闭任意多个流 */ public static void close2(Closeable...ios){ for(Closeable io : ios){ try{ io.close(); }catch(IOException e){ e.printStackTrace(); } } } /** *jdk1.7开始有的功能:try...with...resource *在jdk1.9得到提升,可以直接传入对象,无需 xxx xx = new xxx();这样的写法,直接try(对象1,对象2...) *在try后跟上括号,括号中传入流就可以自动关闭 */ public static void copy2(String filePath,String destPath){ //操作流 try(InputStream is = new FileInputStream(filePath); OutputStream os = new FileOutputStream(destPath)){//没有先后顺序 byte[] flush = new byte[1024*10];//缓冲池 int len = -1;//接收单次读取的长度 while((len = is.read(flush))!=-1){//读取数据 os.write(flush,0,len);//写入数据 } os.flush();//刷新 }catch(IOException e){ e.printStackTrace(); }//这里无需关闭方法 } }