في Java، ما هو النمط الأفضل/الأكثر أمانًا لمراقبة الملف الذي يتم إلحاقه به؟

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

  •  21-08-2019
  •  | 
  •  

سؤال

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

في برنامج Java، أرغب في مراقبة هذا الملف، وعندما يتم إلحاق سطر، اقرأ السطر الجديد وقم بالتفاعل وفقًا للمحتويات.تجاهل مشكلة تحليل ملف CSV في الوقت الحالي.ما هي أفضل طريقة لمراقبة الملف بحثًا عن التغييرات وقراءة سطر في كل مرة؟

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

تحرير - نظرًا لأن حل الحظر غير ممكن مع الفئات القياسية (شكرًا لهذه الإجابة)، ما هو أقوى حل للاقتراع؟أفضل عدم إعادة قراءة الملف بأكمله في كل مرة لأنه قد يكبر حجمه.

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

المحلول

منذ Java 7 كان هناك نيوواتشسيرفيس () الطريقة على فئة نظام الملفات.

ومع ذلك، هناك بعض التحذيرات:

  • إنها جافا 7 فقط
  • إنها طريقة اختيارية
  • فهو يراقب المجلدات فقط، لذلك عليك التعامل مع الملف بنفسك، والقلق بشأن نقل الملف وما إلى ذلك

قبل Java 7، لم يكن ذلك ممكنًا مع واجهات برمجة التطبيقات القياسية.

لقد جربت ما يلي (الاقتراع على فاصل زمني قدره ثانية واحدة) ويعمل (فقط تتم الطباعة قيد المعالجة):

  private static void monitorFile(File file) throws IOException {
    final int POLL_INTERVAL = 1000;
    FileReader reader = new FileReader(file);
    BufferedReader buffered = new BufferedReader(reader);
    try {
      while(true) {
        String line = buffered.readLine();
        if(line == null) {
          // end of file, start polling
          Thread.sleep(POLL_INTERVAL);
        } else {
          System.out.println(line);
        }
      }
    } catch(InterruptedException ex) {
     ex.printStackTrace();
    }
  }

نظرًا لعدم اقتراح أي شخص آخر حلاً يستخدم إصدار Java الحالي، اعتقدت أنني سأضيفه.إذا كان هناك عيوب يرجى إضافتها في التعليقات.

نصائح أخرى

ويمكنك التسجيل للحصول على إخطار من قبل نظام الملفات إذا حدث أي تغيير في الملف باستخدام الطبقة WatchService. وهذا يتطلب Java7، وهنا على الرابط لتوثيق http://docs.oracle كوم / javase / تعليمي / الأساسية / الإعلام والتوعية / notification.html

وهنا رمز المتكررة للقيام بذلك:

public FileWatcher(Path dir) {
   this.watcher = FileSystems.getDefault().newWatchService();
   WatchKey key = dir.register(watcher, ENTRY_MODIFY);
}

void processEvents() {
    for (;;) {
        // wait for key to be signalled
        WatchKey key;
        try {
            key = watcher.take();
        } catch (InterruptedException x) {
            return;
        }

        for (WatchEvent<?> event : key.pollEvents()) {
            WatchEvent.Kind<?> kind = event.kind();

            if (kind == OVERFLOW) {
                continue;
            }
            // Context for directory entry event is the file name of entry
            WatchEvent<Path> ev = cast(event);
            Path name = ev.context();
            Path child = dir.resolve(name);
            // print out event
            System.out.format("%s: %s file \n", event.kind().name(), child);
        }
        // reset key and remove from set if directory no longer accessible
        boolean valid = key.reset();
    }
}

واستخدام جافا 7 في WatchService أو جزء من NIO.2

<اقتباس فقرة>   

تم تصميم API WatchService للتطبيقات التي تحتاج إلى أن يتم إعلامك عن أحداث تغيير الملف.

وهذا غير ممكن مع الطبقات مكتبة القياسية. انظر هذا السؤال للحصول على مزيد من التفاصيل.

لالاقتراع كفاءة فإنه سوف يكون من الأفضل استخدام الوصول العشوائي . وسوف يساعد إذا كنت تتذكر الموقف من نهاية الأخيرة من الملف وبدء القراءة من هناك.

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

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

ولقد اختبرت بنجاح هاتين الطبقتين على كل Windoze و Linux. أود كثيرا أن أعرف إذا كان هناك بعض شرط (مثل نظام التشغيل) الذي فشلوا.

وفئة # 1:

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;

public class FileAppender {

    public static void main(String[] args) throws Exception {
        if ((args != null) && (args.length != 0)) throw
            new IllegalArgumentException("args is not null and is not empty");

        File file = new File("./file.txt");
        int numLines = 1000;
        writeLines(file, numLines);
    }

    private static void writeLines(File file, int numLines) throws Exception {
        PrintWriter pw = null;
        try {
            pw = new PrintWriter( new FileWriter(file), true );
            for (int i = 0; i < numLines; i++) {
                System.out.println("writing line number " + i);
                pw.println("line number " + i);
                Thread.sleep(100);
            }
        }
        finally {
            if (pw != null) pw.close();
        }
    }

}

وفئة # 2:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class FileMonitor {

    public static void main(String[] args) throws Exception {
        if ((args != null) && (args.length != 0)) throw
            new IllegalArgumentException("args is not null and is not empty");

        File file = new File("./file.txt");
        readLines(file);
    }

    private static void readLines(File file) throws Exception {
        BufferedReader br = null;
        try {
            br = new BufferedReader( new FileReader(file) );
            while (true) {
                String line = br.readLine();
                if (line == null) { // end of file, start polling
                    System.out.println("no file data available; sleeping..");
                    Thread.sleep(2 * 1000);
                }
                else {
                    System.out.println(line);
                }
            }
        }
        finally {
            if (br != null) br.close();
        }
    }

}

ومما يؤسف له، والطبقة TailInputStream، والتي يمكن استخدامها لمراقبة نهاية الملف، ليست واحدة من الطبقات منصة جافا القياسية، ولكن هناك عدد قليل من التطبيقات على شبكة الإنترنت. يمكنك العثور على تنفيذ الطبقة TailInputStream جنبا إلى جنب مع مثال الاستخدام على http://www.greentelligent.com/java / tailinputstream .

والإستطلاع، إما على دورة متسقة أو على دورة عشوائية؛ 200-2000ms يجب أن تكون جيدة استطلاع عشوائي فترة الفاصل.

وتحقق أمرين ...

إذا كان لديك لمراقبة نمو الملف، ثم تحقق من عدد EOF / بايت، وتأكد من أن مقارنة وFileAccess وأو fileWrite مرات مع استطلاع معشوقة. إذا (>)، ثم تمت كتابة الملف.

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

والتحقق من وجود إما الملكية وحدها لن بالضرورة تحصل على دولة مضمونة من كتب ++ <م> و القيام به في الواقع ومتاحة للاستخدام.

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