2009-07-06 93 views
3

下面的代碼給我一個System.IO.IOException異常,消息'進程無法訪問文件'。爲什麼使用C1ZipFile後不能刪除這個文件?

private void UnPackLegacyStats() 
{ 
    DirectoryInfo oDirectory; 
    XmlDocument oStatsXml; 

    //Get the directory 
    oDirectory = new DirectoryInfo(msLegacyStatZipsPath); 

    //Check if the directory exists 
    if (oDirectory.Exists) 
    { 
    //Loop files 
    foreach (FileInfo oFile in oDirectory.GetFiles()) 
    { 
     //Check if file is a zip file 
     if (C1ZipFile.IsZipFile(oFile.FullName)) 
     { 
     //Open the zip file 
     using (C1ZipFile oZipFile = new C1ZipFile(oFile.FullName, false)) 
     { 
      //Check if the zip contains the stats 
      if (oZipFile.Entries.Contains("Stats.xml")) 
      { 
      //Get the stats as a stream 
      using (Stream oStatsStream = oZipFile.Entries["Stats.xml"].OpenReader()) 
      { 
       //Load the stats as xml 
       oStatsXml = new XmlDocument(); 
       oStatsXml.Load(oStatsStream); 

       //Close the stream 
       oStatsStream.Close(); 
      } 

      //Loop hit elements 
      foreach (XmlElement oHitElement in oStatsXml.SelectNodes("/*/hits")) 
      { 
       //Do stuff 
      }     
      } 

      //Close the file 
      oZipFile.Close(); 
     } 
     } 

     //Delete the file 
     oFile.Delete(); 
    } 
    } 
} 

我很努力地看到文件仍然可以鎖定在哪裏。所有可能保存在文件句柄上的對象都在使用塊中,並且顯式關閉。

是否使用FileInfo對象而不是靜態GetFiles方法返回的字符串?

任何想法?

+0

你究竟在哪裏得到異常? – 2009-07-06 18:00:47

+0

@Joshua - On oFile.Delete(); – stevehipwell 2009-07-07 07:41:44

回答

1

我假設你在oFile.Delete調用中出錯。我能夠重現這個錯誤。有趣的是,該錯誤只發生在文件爲而非的zip文件中。這是你看到的行爲嗎?

看起來,C1ZipFile.IsZipFile調用在不是zip文件時沒有釋放該文件。通過使用FileStream而不是將文件路徑作爲字符串傳遞(IsZipFile函數接受),我能夠避免此問題。

所以下面的修改您的代碼似乎工作:

if (oDirectory.Exists) 
{ 
    //Loop files 
    foreach (FileInfo oFile in oDirectory.GetFiles()) 
    { 
     using (FileStream oStream = new FileStream(oFile.FullName, FileMode.Open)) 
     { 
      //Check if file is a zip file 
      if (C1ZipFile.IsZipFile(oStream)) 
      { 
      // ... 
      } 
     } 
     //Delete the file 
     oFile.Delete(); 
    } 
}  

爲應對這一問題的原題:我不知道是否有可能知道,如果一個文件可以不嘗試刪除刪除它。你總是可以編寫一個函數,試圖刪除文件並捕獲錯誤,如果不能,然後返回一個指示刪除是否成功的布爾值。

1

我只是猜測:你確定oZipFile.Close()足夠嗎?也許你必須調用oZipFile.Dispose()或oZipFile.Finalize()來確保它實際上釋放了資源。

+0

oZipFile位於使用塊中,不會公開這兩種方法之一。 – stevehipwell 2009-07-07 07:44:59

2

我在代碼中看不到問題,一切都很正常。要檢查的問題出在C1ZipFile我建議你初始化,而不是從文件初始化從流壓縮,所以你明確地關閉流:

//Open the zip file 
using (Stream ZipStream = oFile.OpenRead()) 
using (C1ZipFile oZipFile = new C1ZipFile(ZipStream, false)) 
{ 
    // ... 

其他幾個建議:

  • 你並不需要調用Close()方法,用使用(...),刪除它們。
  • 移動xml處理(循環命中元素)超過了壓縮處理,即壓縮文件關閉後,所以您儘可能少地保持文件打開。
+0

現在我正在使用一切的流,沒有傳遞文件路徑。這似乎解決了這個問題,雖然我認爲它是對文件而不是zip文件對象鎖定的IsZipFile()調用。 – stevehipwell 2009-07-07 08:05:36

1

更可能的是,它不會被丟棄,任何時候您訪問託管代碼(流,文件等)之外的內容時,您必須處理它們。我學習了Asp.NET和圖像文件的艱難方式,它會填滿你的內存,崩潰你的服務器等。

1

爲了完整性我擺出我的工作代碼,因爲更改來自多個來源。

private void UnPackLegacyStats() 
{ 
    DirectoryInfo oDirectory; 
    XmlDocument oStatsXml; 

    //Get the directory 
    oDirectory = new DirectoryInfo(msLegacyStatZipsPath); 

    //Check if the directory exists 
    if (oDirectory.Exists) 
    { 
    //Loop files 
    foreach (FileInfo oFile in oDirectory.GetFiles()) 
    { 
     //Set empty xml 
     oStatsXml = null; 

     //Load file into a stream 
     using (Stream oFileStream = oFile.OpenRead()) 
     { 
     //Check if file is a zip file 
     if (C1ZipFile.IsZipFile(oFileStream)) 
     { 
      //Open the zip file 
      using (C1ZipFile oZipFile = new C1ZipFile(oFileStream, false)) 
      { 
      //Check if the zip contains the stats 
      if (oZipFile.Entries.Contains("Stats.xml")) 
      { 
       //Get the stats as a stream 
       using (Stream oStatsStream = oZipFile.Entries["Stats.xml"].OpenReader()) 
       { 
       //Load the stats as xml 
       oStatsXml = new XmlDocument(); 
       oStatsXml.Load(oStatsStream); 
       } 
      } 
      } 
     } 
     } 

     //Check if we have stats 
     if (oStatsXml != null) 
     { 
     //Process XML here 
     } 

     //Delete the file 
     oFile.Delete(); 
    } 
    } 
} 

的主要教訓我從中學到的管理在一個地方調用代碼文件的訪問,而不是讓其他組件管理自己的文件訪問。當您想在其他組件完成任務後再次使用該文件時,這是最合適的。

雖然這需要更多的代碼,但您必須相信某個組件已正確處理該流,但您可以清楚地看到該流的處理位置(在使用結束時)。

相關問題