2012-09-11 55 views
0

我有這樣的方法:聲納違反:「法可能無法在異常關閉流」

private void unZipElementsTo(String inputZipFileName, String destPath) throws FileNotFoundException, IOException { 

     OutputStream out = null; 
     InputStream in = null; 
     ZipFile zf = null; 

     try { 
      zf = new ZipFile(inputZipFileName); 

      for (Enumeration<? extends ZipEntry> em = zf.entries(); em.hasMoreElements();) { 
       ZipEntry entry = em.nextElement(); 
       String targetFile = destPath + FILE_SEPARATOR + entry.toString().replace("/", FILE_SEPARATOR); 
       File temp = new File(targetFile); 

       if (!temp.getParentFile().exists()) { 
        temp.getParentFile().mkdirs(); 
       } 

       in = zf.getInputStream(entry); 

       out = new FileOutputStream(targetFile); 
       byte[] buf = new byte[4096]; 
       int len; 
       while ((len = in.read(buf)) > 0) { 
        out.write(buf, 0, len); 
       } 
       out.flush(); 
       out.close(); 
       in.close(); 
      } 
     } 
     finally 
     { 
      if (out!=null) out.close(); 
      if (zf!=null) zf.close(); 
      if (in!=null) in.close(); 
     } 
    } 

對於這種方法聲納給我這個違規:

壞實踐 - 方法可能無法在異常 unZipElementsTo(字符串,字符串)關閉流可能無法在例外

關閉流,但是,我看不出有任何違規行爲存在。也許,這只是一個假陽性?

回答

7

沒錯。 方法OutputStream.close()本身可能會引發異常。 如果發生這種情況,例如在您的finally{}區塊的第一行,其他流將保持打開狀態。

+3

一個很好的做法是使用一個特殊的工具方法來默默地關閉流,即關閉或吞嚥異常,因爲你不能從反正這樣的異常中恢復: 公共靜態closeSilently(OutputStream的OS){ 嘗試{ os.close(); } catch(IOException ex ex){} } – wajda

+0

流上關閉的IOException可能表示文件未寫入磁盤。讓它傳播比靜默地忽略它要安全得多。 – Vadzim

2

如果out.close()zf.close()finally塊中拋出異常,則其他關閉將不會執行。

+0

您能否提供任何關於快速修復的建議? – user471011

2

另外,如果您使用的是Java 7或更高版本,可以使用新的嘗試,與資源的機制,它處理的密切爲您服務。有關此新機制的詳細信息,請參閱:http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

請注意,try-with-resources也適用於打開和關閉的多個對象,並仍保留對象將按其構造的相反順序關閉的保證。請在同一頁面上發帖:

請注意,資源的關閉方法是按照其創建的相反順序調用的。