zoukankan      html  css  js  c++  java
  • Java之关闭流

    Java IO包装流如何关闭?

    关闭流的实例在下面,往后拖就OK了

    问题:

    (1)JAVA的IO流使用了装饰模式,关闭最外面的流的时候会自动调用被包装的流的close()方吗?

    (2)如果按顺序关闭流,是从内层流到外层流关闭还是从外层到内存关闭?

    问题(1)解释:

    复制代码
    如下例子代码:
      FileInputStream is = new FileInputStream(".");   
      BufferedInputStream bis = new BufferedInputStream(is);  
      bis.close();
    
     
    从设计模式上看:
    java.io.BufferedInputStream是java.io.InputStream的装饰类。
    BufferedInputStream装饰一个 InputStream 使之具有缓冲功能,is要关闭只需要调用最终被装饰出的对象的 close()方法即可,因为它最终会调用真正数据源对象的 close()方法。
     
    BufferedInputStream的close方法中对InputStream进行了关闭,下面是jdk中附带的源代码:
     java.io.BufferedInputStream的api:
    close
    public void close()throws IOException 关闭此输入流并释放与该流关联的所有系统资源。
    复制代码

    因此,可以只调用外层流的close方法关闭其装饰的内层流,验证例子:

    复制代码
    public static void main(String[] args) throws Exception {
            FileOutputStream fos = new FileOutputStream("d:\a.txt");
            OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
            BufferedWriter bw = new BufferedWriter(osw);
            bw.write("java IO close test");
             
            bw.close();
          
         }

    验证ok
    复制代码

    问题(2)解释:如果不想使用(1)方式关闭流,可以逐个关闭流(可能大家比较习惯吧)

    复制代码
    如下例子: 
    public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream("d:\a.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); BufferedWriter bw = new BufferedWriter(osw); bw.write("java IO close test"); //从内带外顺序顺序会报异常 fos.close(); osw.close(); bw.close(); }
    报出异常:

    Exception in thread "main" java.io.IOException: Stream closed
    at sun.nio.cs.StreamEncoder.ensureOpen(StreamEncoder.java:26)
    at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:99)
    at java.io.OutputStreamWriter.write(OutputStreamWriter.java:190)
    at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:111)
    at java.io.BufferedWriter.close(BufferedWriter.java:246)
    at com.my.test.QQ.main(QQ.java:22)


    如下例子:
     public static void main(String[] args) throws Exception {
            FileOutputStream fos = new FileOutputStream("d:\a.txt");
            OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
            BufferedWriter bw = new BufferedWriter(osw);
            bw.write("java IO close test");
    
            // 从外到内顺序关闭ok
            bw.close();
            osw.close();
            fos.close();
        }

    验证ok
     
    复制代码

    一般情况下是:先打开的后关闭,后打开的先关闭

    另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b

    例如处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b

    当然完全可以只关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法

    如果将节点流关闭以后再关闭处理流,会抛出IO异常;

    Java之关闭流

    我们深知在操作Java流对象后要将流关闭,但往往事情不尽人意,大致有以下几种不能一定将流关闭的写法:

    1.在try中关流,而没在finally中关流

    [java] view plain copy
     
    1. try {  
    2.     OutputStream out = new FileOutputStream("");  
    3.     // ...操作流代码  
    4.     out.close();  
    5. catch (Exception e) {  
    6.     e.printStackTrace();  
    7. }  

    正确写法:

    [java] view plain copy
     
    1. OutputStream out = null;  
    2. try {  
    3.     out = new FileOutputStream("");  
    4.     // ...操作流代码  
    5. catch (Exception e) {  
    6.     e.printStackTrace();  
    7. finally {  
    8.     try {  
    9.         if (out != null) {  
    10.             out.close();  
    11.         }  
    12.     } catch (Exception e) {  
    13.         e.printStackTrace();  
    14.     }  
    15. }  

    2.在关闭多个流时因为嫌麻烦将所有关流的代码丢到一个try中

    [java] view plain copy
     
    1. OutputStream out = null;  
    2. OutputStream out2 = null;  
    3. try {  
    4.     out = new FileOutputStream("");  
    5.     out2 = new FileOutputStream("");  
    6.     // ...操作流代码  
    7. catch (Exception e) {  
    8.     e.printStackTrace();  
    9. finally {  
    10.     try {  
    11.         if (out != null) {  
    12.             out.close();// 如果此处出现异常,则out2流没有被关闭  
    13.         }  
    14.         if (out2 != null) {  
    15.             out2.close();  
    16.         }  
    17.     } catch (Exception e) {  
    18.         e.printStackTrace();  
    19.     }  
    20. }  

    正确写法:

    [java] view plain copy
     
    1. OutputStream out = null;  
    2. OutputStream out2 = null;  
    3. try {  
    4.     out = new FileOutputStream("");  
    5.     out2 = new FileOutputStream("");  
    6.     // ...操作流代码  
    7. catch (Exception e) {  
    8.     e.printStackTrace();  
    9. finally {  
    10.     try {  
    11.         if (out != null) {  
    12.             out.close();// 如果此处出现异常,则out2流也会被关闭  
    13.         }  
    14.     } catch (Exception e) {  
    15.         e.printStackTrace();  
    16.     }  
    17.     try {  
    18.         if (out2 != null) {  
    19.             out2.close();  
    20.         }  
    21.     } catch (Exception e) {  
    22.         e.printStackTrace();  
    23.     }  
    24. }  

    3.在循环中创建流,在循环外关闭,导致关闭的是最后一个流

    [java] view plain copy
     
    1. OutputStream out = null;  
    2. try {  
    3.     for (int i = 0; i < 10; i++) {  
    4.         out = new FileOutputStream("");  
    5.         // ...操作流代码  
    6.     }  
    7. catch (Exception e) {  
    8.     e.printStackTrace();  
    9. finally {  
    10.     try {  
    11.         if (out != null) {  
    12.             out.close();  
    13.         }  
    14.     } catch (Exception e) {  
    15.         e.printStackTrace();  
    16.     }  
    17. }  

    正确写法:

    [java] view plain copy
     
    1. for (int i = 0; i < 10; i++) {  
    2.     OutputStream out = null;  
    3.     try {  
    4.         out = new FileOutputStream("");  
    5.         // ...操作流代码  
    6.     } catch (Exception e) {  
    7.         e.printStackTrace();  
    8.     } finally {  
    9.         try {  
    10.             if (out != null) {  
    11.                 out.close();  
    12.             }  
    13.         } catch (Exception e) {  
    14.             e.printStackTrace();  
    15.         }  
    16.     }  
    17. }  

    PS:在Java7中,关闭流这种繁琐的事情再也不用我们自己敲代码了:

    [java] view plain copy
     
    1. try (OutputStream out = new FileOutputStream("")){  
    2.     // ...操作流代码  
    3. catch (Exception e) {  
    4.     e.printStackTrace();  
    5. }  

    只要实现的自动关闭接口(Closeable)的类都可以在try结构体上定义,java会自动帮我们关闭,及时在发生异常的情况下也会。可以在try结构体上定义多个,用分号隔开即可,如:

    [java] view plain copy
     
      1. try (OutputStream out = new FileOutputStream("");OutputStream out2 = new FileOutputStream("")){  
      2.     // ...操作流代码  
      3. catch (Exception e) {  
      4.     throw e;  
      5. }  
  • 相关阅读:
    Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持
    Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持
    Atitit.得到网络邻居列表java php c#.net python
    Atitit.得到网络邻居列表java php c#.net python
    Atitit.软件开发的非功能性需求attilax 总结
    Atitit.软件开发的非功能性需求attilax 总结At
    Atitit. servlet 与 IHttpHandler  ashx  listen 和HttpModule的区别与联系 原理理论 架构设计   实现机制    java php c#.net j
    Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle
    Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle
    Atitit.数据索引 的种类以及原理实现机制 索引常用的存储结构
  • 原文地址:https://www.cnblogs.com/handsome1013/p/7403211.html
Copyright © 2011-2022 走看看