[英]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.