كيف يمكنني قفل ملف باستخدام جافا (إن أمكن)

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

  •  02-07-2019
  •  | 
  •  

سؤال

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

للتوضيح:

لدي تطبيق Java يسرد مجلدًا ويفتح كل ملف في القائمة لمعالجته.يقوم بمعالجة كل ملف تلو الآخر.تتكون معالجة كل ملف من قراءته وإجراء بعض الحسابات بناءً على محتوياته وتستغرق حوالي دقيقتين.لدي أيضًا تطبيق Java آخر يفعل نفس الشيء ولكنه بدلاً من ذلك يكتب على الملف.ما أريده هو أن أكون قادرًا على تشغيل هذه التطبيقات في نفس الوقت بحيث يسير السيناريو على هذا النحو.يسرد تطبيق ReadApp المجلد ويبحث عن الملفات A وB وC.يفتح الملف A ويبدأ القراءة.يسرد تطبيق WriteApp المجلد ويبحث عن الملفات A وB وC.يفتح الملف A، ويرى أنه مفتوح (بسبب استثناء أو بأي طريقة أخرى) وينتقل إلى الملف B.ينهي ReadApp الملف A ويستمر إلى B.يرى أنه مفتوح ويستمر إلى C.من المهم ألا يكتب تطبيق WriteApp بينما يقرأ تطبيق ReadApp نفس الملف أو العكس.إنها عمليات مختلفة.

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

المحلول

ربما يكون FileChannel.lock هو ما تريده.

FileInputStream in = new FileInputStream(file);
try {
    java.nio.channels.FileLock lock = in.getChannel().lock();
    try {
        Reader reader = new InputStreamReader(in, charset);
        ...
    } finally {
        lock.release();
    }
} finally {
    in.close();
}

(تنصل:لم يتم تجميع التعليمات البرمجية وبالتأكيد لم يتم اختبارها.)

لاحظ القسم المعنون "تبعيات النظام الأساسي" في ملف مستند API لـ FileLock.

نصائح أخرى

لا تستخدم الفصول الدراسية فيjava.io الحزمة، بدلاً من ذلك استخدم java.nio طَرد .هذا الأخير لديه FileLock فصل.يمكنك تطبيق القفل على أ FileChannel.

 try {
        // Get a file channel for the file
        File file = new File("filename");
        FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

        // Use the file channel to create a lock on the file.
        // This method blocks until it can retrieve the lock.
        FileLock lock = channel.lock();

        /*
           use channel.lock OR channel.tryLock();
        */

        // Try acquiring the lock without blocking. This method returns
        // null or throws an exception if the file is already locked.
        try {
            lock = channel.tryLock();
        } catch (OverlappingFileLockException e) {
            // File is already locked in this thread or virtual machine
        }

        // Release the lock - if it is not null!
        if( lock != null ) {
            lock.release();
        }

        // Close the file
        channel.close();
    } catch (Exception e) {
    }

إذا كنت تستطيع استخدام جافا نيو (JDK 1.4 أو أكبر)، ثم أعتقد أنك تبحث عنه java.nio.channels.FileChannel.lock()

FileChannel.lock()

يستخدم java.nio.channels.FileLock بالتزامن مع java.nio.channels.FileChannel

قد لا يكون هذا ما تبحث عنه، ولكن من مصلحة التعامل مع المشكلة من زاوية أخرى....

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

استخدم RandomAccessFile، واحصل على القناة الخاصة به، ثم اتصل بـ lock().لا تتمتع القناة التي توفرها تدفقات الإدخال أو الإخراج بامتيازات كافية لقفلها بشكل صحيح.تأكد من استدعاء unlock() في الكتلة الأخيرة (لا يؤدي إغلاق الملف بالضرورة إلى تحرير القفل).

لقد وجدت نفس المشكلة منذ عدة سنوات عندما كتبت تطبيقًا يتطلب من عدة مستخدمين على نظامي التشغيل MacOS/Windows مشاركة نفس البيانات في ملفات متعددة.لم يعمل قفل الملفات على نظام التشغيل MacOS، لذا قمت بإنشاء فئة "ioFile" الخاصة بي والتي حافظت على السجل الخاص بها للوصول إلى الملفات - open r/o، open r/w، وما إلى ذلك، ومن "يمتلك" القفل.هذه هي الطريقة الوحيدة في ذلك الوقت التي يمكنني من خلالها التحكم في الوصول من مستخدمين مختلفين على أجهزة مختلفة باستخدام أنظمة تشغيل مختلفة.

يوجد أدناه نموذج لرمز مقتطف لقفل ملف حتى تتم معالجته بواسطة JVM.

 public static void main(String[] args) throws InterruptedException {
    File file = new File(FILE_FULL_PATH_NAME);
    RandomAccessFile in = null;
    try {
        in = new RandomAccessFile(file, "rw");
        FileLock lock = in.getChannel().lock();
        try {

            while (in.read() != -1) {
                System.out.println(in.readLine());
            }
        } finally {
            lock.release();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

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

public class FileReader{
  public void read() {
    synchronized (this) {
      //put you file access here
    }
  }
}
package tips.javabeat.nio.lock;  

import java.io.*;  
import java.nio.channels.FileChannel;  
import java.nio.channels.FileLock;  

public class FileLockTest {  

    public static void main(String[] args) throws Exception {  

       RandomAccessFile file = null;  

         FileLock fileLock = null;  

         try 

         {  

             file = new RandomAccessFile("FileToBeLocked", "rw");  

             FileChannel fileChannel = file.getChannel();  



             fileLock = fileChannel.tryLock();  

             if (fileLock != null){  

                 System.out.println("File is locked");  

                 accessTheLockedFile();  

             }  

         }finally{  

             if (fileLock != null){  

                 fileLock.release();  

             }  

         }  

     }  



     static void accessTheLockedFile(){  

        try{  

         FileInputStream input = new FileInputStream("FileToBeLocked");  

          int data = input.read();  

            System.out.println(data);  

      }catch (Exception exception){  

             exception.printStackTrace();  
        }  

     }  

يمكنك استخدام واجهات برمجة التطبيقات java.nio.* لقفل الملف.ومع ذلك، هذا لا يضمن القفل، فهو يعتمد على ما إذا كان نظام التشغيل الأساسي يدعم القفل أم لا. كما أفهم أن أنظمة التشغيل مثل Linux لا تدعم القفل، وبالتالي لا يمكنك القفل حتى إذا كنت تستخدم واجهات برمجة التطبيقات هذه

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