从正在使用Java编写的文件中读取[改进]

时间:2017-12-25 20:41:59

标签: java multithreading file

我想从另一个应用程序/进程正在编写的文件中读取。

我在另一个问题中找到的这段代码完成了这项工作:它在写入文件时读取文件,只读取新内容。

即使没有数据添加到文件中,也会消耗大量CPU的问题。如何优化此代码?

  • 使用计时器?还是要暂停的thread.sleep?

要添加的另一件事是,我尝试编写的整个程序实时读取文件并处理其内容。所以这意味着thread.sleep或计时器将暂停我的整个程序。我正在寻找的理想改进不是等待几秒钟,而是为了某个事件发生=> 添加了新数据。这可能吗?



public class FileReader {

    public static void main(String args[]) throws Exception {
        if(args.length>0){
            File file = new File(args[0]);
            System.out.println(file.getAbsolutePath());
            if(file.exists() && file.canRead()){
                long fileLength = file.length();
                readFile(file,0L);
                while(true){

                    if(fileLength<file.length()){
                        readFile(file,fileLength);
                        fileLength=file.length();
                    }
                }
            }
        }else{
            System.out.println("no file to read");
        }
    }

    public static void readFile(File file,Long fileLength) throws IOException {
        String line = null;

        BufferedReader in = new BufferedReader(new java.io.FileReader(file));
        in.skip(fileLength);
        while((line = in.readLine()) != null)
        {
            System.out.println(line);
        }
        in.close();
    }
}
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

  

我正在寻找的理想改进不是等待几秒钟,而是   对于某个事件的发生=&gt;添加了新数据。这可能吗?

最佳解决方案:数据推送

产生内容的应用程序应通知其他应用程序,因为它可能会读取内容。

您可以使用任何可在两个不同应用程序之间传达信息的渠道。

例如,通过使用编写器更新的特定文件来通知要读取的新内容 作者可以在此文件中写入/覆盖更新日期,只有在此日期之后没有读取任何内容的情况下,读者才会读取数据文件。

更强大的方式但是有更多的开销可能会从阅读器方面暴露通知服务 为什么不使用REST服务 通过这种方式,作者可以在新内容准备就绪时通过服务通知读者。

  

要添加的另一件事,我试图写的整个程序读取了一个   实时归档并处理其内容。所以这意味着   thread.sleep或计时器将暂停我的整个程序。

解决方案解决方案:由特定线程执行的数据提取

你可能有一个多核CPU 因此,创建一个单独的线程来读取生成的文件,以允许应用程序的其他线程可以运行 此外,您还可以执行一些定期暂停:Thread.sleep()以优化阅读主题完成的核心使用。

它可能看起来像:

Thread readingThread = new Thread(new MyReadingProcessing());
readingThread.start();

其中MyReadingProcessingRunnable

public class MyReadingProcessing implements Runnable{

     public void run(){
          while (true){
               readFile(...);
               try{
                  Thread.sleep(1000); // 1 second here but choose the deemed reasonable time according the metrics of your producer application
               }  
               catch(InterruptedException e){
                  Thread.currentThread().interrupt();
               }
               if (isAllReadFile()){ // condition to stop the reading process
                   return;
               }
          }
     }
}

答案 1 :(得分:0)

而不是繁忙的等待循环使用WatchService更改目录条目。

Path path = Paths.get("...");
try (WatchService watchService =
            path.getFileSystem().newWatchService()) {
    WatchKey watchKey = path.register(watchService,
            StandardWatchEventKinds.ENTRY_MODIFY);
    for (;;) { // watchKey.poll with timeout, or take, blocking
        WatchKey taken = watchService.take();
        for (WatchEvent<?> event : taken.pollEvents()) {
            Path changedPath = (Path) event.context();
            if (changedPath.equals(path)) {
                ...
            }
        }
        boolean valid = taken.reset();
        if (!valid) {
            ... unregistered
        }
    }
}

请注意,上述内容必须适用于使用民意调查或拍摄。