Java 7 watchservice get file change offset

前端 未结 2 1992
耶瑟儿~
耶瑟儿~ 2021-02-06 06:08

I\'ve just been playing around with the Java 7 WatchService for monitoring a file for change.

Here\'s a little bit of code I knocked up:

WatchService wat         


        
2条回答
  •  一整个雨季
    2021-02-06 06:13

    Okay, here is another answer as a variation of my previous one for changes at any file position (diff). Now the somewhat simpler case is files only being appended (tail).

    How to build:

    
    
        4.0.0
    
        de.scrum-master.tools
        SO_WatchServiceChangeLocationInFile
        1.0-SNAPSHOT
    
        
            UTF-8
        
    
        
            
                
                    maven-compiler-plugin
                    3.1
                    
                        1.7
                        1.7
                    
                
            
        
    
        
            
                commons-io
                commons-io
                
                2.5-SNAPSHOT
            
        
    
        
            
                apache.snapshots
                http://repository.apache.org/snapshots/
            
        
    
    

    As you can see, we use Apache Commons IO here. (Why a snapshot version? Follow the link in the XML comment if you are interested.)

    Source code:

    package de.scrum_master.app;
    
    import org.apache.commons.io.input.Tailer;
    import org.apache.commons.io.input.TailerListenerAdapter;
    
    import java.io.IOException;
    import java.nio.charset.Charset;
    import java.nio.file.*;
    
    import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
    
    public class FileTailWatcher {
        public static final String DEFAULT_WATCH_DIR = "watch-dir";
        public static final int DEFAULT_WATCH_INTERVAL = 5;
    
        private Path watchDir;
        private int watchInterval;
        private WatchService watchService;
    
        public FileTailWatcher(Path watchDir, int watchInterval) throws IOException {
            if (!Files.isDirectory(watchDir))
                throw new IllegalArgumentException("Path '" + watchDir + "' is not a directory");
            this.watchDir = watchDir;
            this.watchInterval = watchInterval;
            watchService = FileSystems.getDefault().newWatchService();
        }
    
        public static class MyTailerListener extends TailerListenerAdapter {
            public void handle(String line) {
                System.out.println(line);
            }
        }
    
        public void run() throws InterruptedException, IOException {
            try (DirectoryStream dirEntries = Files.newDirectoryStream(watchDir)) {
                for (Path file : dirEntries)
                    createTailer(file);
            }
            watchDir.register(watchService, ENTRY_CREATE);
            while (true) {
                WatchKey watchKey = watchService.take();
                for (WatchEvent event : watchKey.pollEvents())
                    createTailer(watchDir.resolve((Path) event.context()));
                watchKey.reset();
                Thread.sleep(1000 * watchInterval);
            }
        }
    
        private Tailer createTailer(Path path) {
            if (Files.isDirectory(path))
                return null;
            System.out.println("Creating tailer: " + path);
            return Tailer.create(
                path.toFile(),             // File to be monitored
                Charset.defaultCharset(),  // Character set (available since Commons IO 2.5)
                new MyTailerListener(),    // What should happen for new tail events?
                1000,                      // Delay between checks in ms
                true,                      // Tail from end of file, not from beginning
                true,                      // Close & reopen files in between reads,
                                           // otherwise file is locked on Windows and cannot be deleted
                4096                       // Read buffer size
            );
        }
    
        public static void main(String[] args) throws IOException, InterruptedException {
            String watchDirName = args.length > 0 ? args[0] : DEFAULT_WATCH_DIR;
            int watchInterval = args.length > 2 ? Integer.getInteger(args[2]) : DEFAULT_WATCH_INTERVAL;
            new FileTailWatcher(Paths.get(watchDirName), watchInterval).run();
        }
    }
    

    Now try appending to existing files and/or creating new ones. Everything will be printed to standard output. In a production environment you would maybe display multiple windows or tabs, one for each log file. Whatever...

    @Simon: I hope this one suits your situation better than the more general case and is worth a bounty. :-)

提交回复
热议问题