فقدان الطاقة بعد أن ينتج StreamWriter.Close() ملفًا فارغًا، لماذا؟

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

  •  07-07-2019
  •  | 
  •  

سؤال

حسنًا، للتوضيح؛أنا أقوم بالتطوير لنظام يمكن أن يعاني من انقطاع التيار الكهربائي في أي وقت، وإحدى النقاط التي أقوم باختبارها هي مباشرة بعد كتابة ملف باستخدام StreamWriter.الكود أدناه:

// Write the updated file back out to the Shell directory.
using (StreamWriter shellConfigWriter =
        new StreamWriter(@"D:\xxx\Shell\Config\Game.cfg.bak"))
{
    for (int i = 0; i < configContents.Count; i++)
    {
        shellConfigWriter.WriteLine(configContents[i]);
    }
    shellConfigWriter.Close();
}

FileInfo gameCfgBackup = new FileInfo(@"D:\xxx\Shell\Config\Game.cfg.bak");
gameCfgBackup.CopyTo(@"D:\xxx\Shell\Config\Game.cfg", true);

يكتب محتويات shellConfigWriterList من السلاسل) إلى ملف يستخدم كمخزن مؤقت، ثم يتم نسخه فوق الملف الأصلي.الآن بعد انتهاء هذا الرمز من التنفيذ، يتم فقدان الطاقة، عند بدء النسخ الاحتياطي للملف مرة أخرى Game.cfg موجود وهو بالحجم الصحيح، ولكنه فارغ تمامًا.في البداية اعتقدت أن هذا يرجع إلى تمكين التخزين المؤقت للكتابة على القرص الصلب، ولكن حتى مع إيقاف تشغيله لا يزال يحدث (وإن كان ذلك في كثير من الأحيان).

أي أفكار ستكون موضع ترحيب كبير!

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

هل كانت مفيدة؟

المحلول

والحفاظ على نظام التشغيل من التخزين المؤقت إخراج باستخدام المعلمة FileOptions من منشئ الكائن FileStream ل:

    using (Stream fs = new FileStream(@"D:\xxx\Shell\Config\Game.cfg.bak", FileMode.Create, FileAccess.Write, FileShare.None, 0x1000, FileOptions.WriteThrough))
    using (StreamWriter shellConfigWriter = new StreamWriter(fs))
    {
        for (int i = 0; i < configContents.Count; i++)
        {
            shellConfigWriter.WriteLine(configContents[i]);
        }
        shellConfigWriter.Flush();
        shellConfigWriter.BaseStream.Flush();
    }

نصائح أخرى

بادئ ذي بدء، ليس من الضروري الاتصال shellConfigWriter.Close() هناك.ال using البيان سوف يعتني به.ما قد ترغب في القيام به بدلاً من ذلك للحماية من انقطاع التيار الكهربائي هو الاتصال shellConfigWriter.Flush().


تحديث
شيء آخر قد ترغب في أخذه في الاعتبار هو أنه إذا كان انقطاع التيار الكهربائي يمكن أن يحدث بالفعل أي الوقت، يمكن أن يحدث ذلك في منتصف عملية الكتابة، بحيث تصل بعض البايتات فقط إلى الملف.لا يوجد حقا طريقة لوقف ذلك.

للحماية من هذه السيناريوهات، الإجراء الشائع هو استخدام ملفات إشارة الحالة/الحالة.يمكنك استخدام وجود أو عدم وجود ملف صفر بايت في نظام الملفات يحمل اسمًا معينًا لإخبار برنامجك بالمكان الذي يجب أن يلتقطه مرة أخرى عند استئنافه.ثم لا تقم بإنشاء أو تدمير الملفات التي تؤدي إلى حالة معينة حتى تقوم بذلك بالتأكيد لقد وصلت إلى تلك الحالة وأكملت ما سبق.

الجانب السلبي هنا هو أنه قد يعني التخلص من الكثير من العمل بين الحين والآخر.لكن الفائدة هي أن هذا يعني أن الجزء الوظيفي من شفرتك يبدو طبيعيًا:هناك القليل جدًا من العمل الإضافي الذي يتعين القيام به لجعل النظام قويًا بدرجة كافية.

وترغب في تعيين AutoFlush = true;

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