سؤال

لدي تطبيق Java يراقب مجلدًا لملفات XML الواردة.عندما يتم اكتشاف ملف جديد أحتاج إلى اختبار الملف للتأكد من أنه لا يتم تحديثه حاليًا وأنه مغلق.فكرتي هي الاستخدام ملف.canWrite() لاختبار هذا.هل هناك أي مشكلة في القيام بذلك؟هل هذه طريقة جيدة لاختبار أن الملف قد تمت كتابته بالكامل؟

الأفكار الأخرى التي أطرحها هي:

  • تحليل ملف XML الوارد واختبار أن علامة الإغلاق موجودة.
  • تحقق من وجود حرف EoF.

أنا لست متأكدًا من أن أيًا من هذه الطرق ستتعامل مع جميع السيناريوهات.

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

المحلول

لا، canWrite غير مناسب لهذا الغرض.بشكل عام، سيكون الملف قابلاً للكتابة حتى في حالة كتابة عملية أخرى.

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

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

نظرًا لأنك في هذه الحالة تعمل حصريًا باستخدام XML، فإن البحث عن علامة إغلاق سيعمل، ولكنه ليس مضمونًا - ماذا لو كانت هناك تعليقات بعد الترميز النهائي، أو الكاتب أو ببساطة لا يكتب XML صالحًا؟

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

نصائح أخرى

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

أو إعادة تعريف الاختبار الخاص بك.في هذه الحالة، ربما يمكنك اختبار ما إذا كان الملف لم يتغير خلال فترة زمنية قبل معالجته.

خيار آخر هو تقسيم الكود إلى قسمين، يمكن أن يكون لديك موضوع آخر - ربما مهمة كوارتز - مسؤول عن نقل الملفات النهائية إلى دليل مختلف يعالجه الكود الرئيسي الخاص بك.

شيء واحد يبدو أنه يعمل في Windows هو هذا - إنشاء كائن ملف () يمثل الملف المعني (باستخدام مُنشئ مع اسم الملف الكامل) - قم بإنشاء كائن ملف متطابق ثانٍ ، نفس الطريقة.- حاول firstFile.renameTo( SecondFile)

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

وبما أن اسم الملف nw = اسم الملف القديم، فإنه لا يؤدي إلى إنشاء أي عمل آخر.

بقدر ما أعرف، لا توجد طريقة لمعرفة ما إذا كانت هناك عملية أخرى لديها حاليًا مقبض مفتوح لملف من Java.أحد الخيارات هو استخدام FileLock فئة من io الجديد.هذا غير مدعوم على جميع الأنظمة الأساسية، ولكن إذا كانت الملفات محلية وكانت عملية كتابة الملف متعاونة، فمن المفترض أن يعمل هذا مع أي نظام أساسي يدعم الأقفال.

إذا كنت تتحكم في كل من القارئ والكاتب، فستكون تقنية القفل المحتملة هي إنشاء قفل الدليل - والتي عادة ما تكون عملية ذرية - لمدة عملية القراءة والكتابة.إذا اتبعت هذا النوع من النهج، فيجب عليك إدارة الفشل المحتمل لعملية ما مما يؤدي إلى دليل قفل "معلق".

كما ذكر Cheekysoft، الملفات ليست ذرية وغير مناسبة للقفل.

إذا كنت لا تتحكم في الكاتب - على سبيل المثال إذا تم إنتاجه بواسطة برنامج FTP - فإن تقنية إعادة التسمية أو تقنية تأخير الفترة الزمنية هي أفضل الخيارات المتاحة لك.

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