2009-07-06 97 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(); 
    } 
    } 
} 

的主要教训我从中学到的管理在一个地方调用代码文件的访问,而不是让其他组件管理自己的文件访问。当您想在其他组件完成任务后再次使用该文件时,这是最合适的。

虽然这需要更多的代码,但您必须相信某个组件已正确处理该流,但您可以清楚地看到该流的处理位置(在使用结束时)。

相关问题