[英]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))
{
// ...
其他一些建议:
我只是猜测:你确定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.