簡體   English   中英

使用C1ZipFile后為什么不能刪除此文件?

[英]Why can't this file be deleted after using C1ZipFile?

下面的代碼給了我一個System.IO.IOException,消息'進程無法訪問該文件'。

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方法返回的字符串有關?

有任何想法嗎?

我沒有在你的代碼中看到問題,一切看起來都不錯。 要檢查問題在於C1ZipFile我建議你從流初始化zip,而不是從文件初始化,所以你明確地關閉流:

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

其他一些建議:

  • 您不需要調用Close()方法, 使用(...)刪除它們。
  • 移動xml處理(循環命中元素)超大zip處理,即在zip文件關閉后,所以你盡可能地保持文件打開。

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

我假設您在oFile.Delete調用上遇到錯誤。 我能夠重現這個錯誤。 有趣的是,只有當文件不是 zip文件時才會出現錯誤。 這是你看到的行為嗎?

看來,當它不是zip文件時,C1ZipFile.IsZipFile調用不會釋放該文件。 通過使用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();
    }
}    

回答主題中的原始問題:我不知道是否可以在不嘗試刪除文件的情況下刪除文件。 您總是可以編寫一個嘗試刪除文件的函數,如果不能,則捕獲錯誤,然后返回一個指示刪除是否成功的布爾值。

更多可能它沒有被處理,無論何時你訪問托管代碼之外的東西(流,文件等),你必須處理它們。 我用Asp.NET和Image文件學到了很多東西,它會填滿你的內存,崩潰你的服務器等等。

為了完整起見,我正在構建我的工作代碼,因為更改來自多個來源。

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();
    }
  }
}

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM