لماذا لا يمكن حذف هذا الملف بعد استخدام C1ZipFile؟

StackOverflow https://stackoverflow.com/questions/1087746

  •  23-08-2019
  •  | 
  •  

سؤال

يعطيني الكود التالي 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();
    }
  }
}

الدرس الرئيسي الذي تعلمته من هذا هو إدارة الوصول إلى الملفات في مكان واحد في رمز الاتصال بدلا من السماح بالمكونات الأخرى بإدارة وصول الملفات الخاصة بهم. هذا هو الأكثر ملائمة عندما تريد استخدام الملف مرة أخرى بعد انتهاء المكون الآخر من مهمة.

على الرغم من أن هذا يستغرق مزيدا من التعليمات البرمجية، إلا أنه يمكنك معرفة المكان الذي يتم فيه التخلص منه الدفق (في نهاية الاستخدام)، مقارنة بالضغط على أن أحد المكون قد تم التخلص منه بشكل صحيح من الدفق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top