なぜこのファイルは削除され使用後C1ZipFile?
質問
以下のコードに与えられることになる。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方法は?
そのアイデア?
解決
私はあなたが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();
}
}
被験者における元の質問に応えて:それはファイルがそれを削除しようとせずに削除することができるかどうかを知ることができるかどうかはわかりません。あなたは、常にファイルを削除しようとすると、それができない場合は、エラーをキャッチし、その後、削除が成功したかどうかを示すブール値を返す関数を書くことができます。
他のヒント
ついては影響は少ないと考えてい問題が、見るもの全てokです。チェックで問題があるのでC1ZipFileていただきたい初期化zipストリームからではなく、初期化ファイルからもしくは、こちらをご覧ください。トを明示的に:
//Open the zip file
using (Stream ZipStream = oFile.OpenRead())
using (C1ZipFile oZipFile = new C1ZipFile(ZipStream, false))
{
// ...
その他複数の提案:
- する必要はない呼びClose()メソッドと 利用(...), 削除します。
- 移動xml処理(ループ-ヒットの要素)outsize zip処理、すなわち後、zipファイルcloseing、ファイルとして開業、少なくとも可能です。
私は推測している:あなたはoZipFile.Close()が十分であることを確認してください?おそらく、あなたはそれが実際にリソースを解放したことを確認するoZipFile.Dispose()またはoZipFile.Finalize()を呼び出す必要があります。
可能性が高いそれは、あなたがマネージコード(ストリーム、ファイルなど)の外の何かにアクセスいつに配置されていないあなたはそれらを処分しなければなりません。私はそれがなど、サーバーをクラッシュさ、あなたの記憶をいっぱいになり、Asp.NETと画像ファイルとのハードな方法を学びました。
完全性の利益のために私は自分の作業コードを装っています。
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();
}
}
}
私はこのから学んだ主な教訓は、他のコンポーネントは、独自のファイルアクセスを管理させるのではなく、呼び出し元のコード内の1つの場所にあるファイルへのアクセスを管理することです。あなたは他の成分は、それのタスクを完了した後に、再度ファイルを使用したい場合に最も良いと考えている。
これはもう少しコードがかかりますが、ストリームは、(使用しての終わりに)配置されている。ここで、あなたは明確にコンポーネントが正しくストリームを処分したことを信頼することに比べて、見ることができます。