لماذا لا يمكن حذف هذا الملف بعد استخدام 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 بدلا من السلاسل التي تم إرجاعها بواسطة طريقة Static GetFiles؟
أيه أفكار؟
المحلول
أفترض أنك تحصل على الخطأ في مكالمة ofile.delete. كنت قادرا على إعادة إنتاج هذا الخطأ. ومن المثير للاهتمام، يحدث الخطأ فقط عندما يكون الملف ليس ملف مضغوط. هل هذا هو السلوك الذي تراه؟
يبدو أن مكالمة 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();
}
}
استجابة للسؤال الأصلي في الموضوع: لا أعرف ما إذا كان من الممكن معرفة ما إذا كان يمكن حذف ملف دون محاولة حذفه. يمكنك دائما كتابة وظيفة تحاول حذف الملف وصيد الخطأ إذا لم يتمكن من إرجاع ومن ثم إرجاع منطقي يشير إلى ما إذا كان الحذف ناجحا.
نصائح أخرى
لا أرى مشاكل في التعليمات البرمجية الخاصة بك، كل شيء يبدو جيدا. للتحقق من المشكلة تكمن في C1ZipFile أقترح عليك تهيئة الرمز البريدي من الدفق، بدلا من التهيئة من الملف، لذلك يمكنك إغلاق دفق صراحة:
//Open the zip file
using (Stream ZipStream = oFile.OpenRead())
using (C1ZipFile oZipFile = new C1ZipFile(ZipStream, false))
{
// ...
العديد من الاقتراحات الأخرى:
- لا تحتاج إلى الاتصال بطريقة إغلاق ()، مع استخدام (...), ، احذفهم.
- نقل معالجة XML (عناصر ضرب حلقة) احتياطي المعالجة الرمز البريدي، أي بعد ملف zip المقرب، لذلك يمكنك الاستمرار في فتح الملف على الأقل ممكن.
أنا فقط أظن: هل أنت متأكد من أن 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();
}
}
}
الدرس الرئيسي الذي تعلمته من هذا هو إدارة الوصول إلى الملفات في مكان واحد في رمز الاتصال بدلا من السماح بالمكونات الأخرى بإدارة وصول الملفات الخاصة بهم. هذا هو الأكثر ملائمة عندما تريد استخدام الملف مرة أخرى بعد انتهاء المكون الآخر من مهمة.
على الرغم من أن هذا يستغرق مزيدا من التعليمات البرمجية، إلا أنه يمكنك معرفة المكان الذي يتم فيه التخلص منه الدفق (في نهاية الاستخدام)، مقارنة بالضغط على أن أحد المكون قد تم التخلص منه بشكل صحيح من الدفق.