Java监视目录给我错误的事件文件路径

时间:2014-08-04 09:18:11

标签: java directory java-7

我正在使用JDK7"观看变更目录"特征。但我发现有时它会给我错误的文件路径,用于存档的特定事件。即使文件名是正确的。我在 fedora和ubuntu 中遇到了这个问题 还有其他人遇到过同样的问题。

重现的步骤:

  1. https://dl.dropboxusercontent.com/u/39897681/code/fileOperation.zip下载并解压缩以生成文件。请通过阅读README.txt

  2. 将其配置为生成文件
  3. 通过提供空的源文件夹和文件[用于日志目的]作为输入来运行Sample Java代码。等待一段时间

  4. 通过配置下载内容运行Main.py,使其生成文件和文件夹。

  5. java程序将显示磁盘上但不在列表中的文件列表[从监视目录收到的文件事件生成的列表]

  6. 最初java输出就是没有事件丢失

    节目输出 待处理文件数= 2398 没有文件丢失

    但是我们最终错过了一些文件事件或者在一段时间后错误路径

    待处理文件数= 4552

    findFilesPresentOnDiskButNotInList

    错过的文件是 /data/home/developer/test/folder_0.689628351684/folder_0.0451760705904/folder_0.000447662431096/folder_0.264689686702/folder_0.849536150754/folder_0.216092330336/folder_0.677792564103/folder_0.796242073532

    这里使用绝对路径/data/home/developer/test/folder_0.689628351684/folder_0.0451760705904创建folder_0.0451760705904,但是在日志文件中它正在打印文件夹的其他路径。

    import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
    import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
    import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
    import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
    import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.nio.file.AccessDeniedException;
    import java.nio.file.ClosedWatchServiceException;
    import java.nio.file.FileSystems;
    import java.nio.file.FileVisitResult;
    import java.nio.file.Files;
    import java.nio.file.NoSuchFileException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.SimpleFileVisitor;
    import java.nio.file.WatchEvent;
    import java.nio.file.WatchKey;
    import java.nio.file.WatchService;
    import java.nio.file.attribute.BasicFileAttributes;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Scanner;
    
    public class DirectoryWatcher implements Runnable {
    // list of files whose events were received during creation,modification and delete operation
    public static List<String> filesList = new ArrayList<String>();
    // list of source folder path that we want to monitor
    public static List<Path> srcPaths;
    private WatchService watcher;
    private Map<WatchKey, Path> keys;
    private String module = "DirectoryWatcher-";
    private boolean trace = false;
    FilesetSimpleFileVisitor SFRFileVisitor = new FilesetSimpleFileVisitor();
    
    /**
     * Points to the log file which contains all the information about the
     * events received by directory watcher. Any event that is received by
     * directory watcher is logged into this file with the type of event. eg
     * CREATE <full file path>
     */
    public static String LOG_FILE_PATH = null;
    public static PrintWriter logFileWriter = null;
    
    public DirectoryWatcher(List<Path> srcPaths) throws IOException {
    super();
    this.srcPaths = srcPaths;
    initWatchService();
    registerTopLevelSrcFolder();
    new Thread(this).start();
    }
    
    @SuppressWarnings("unchecked")
    static <T> WatchEvent<T> cast(WatchEvent<?> event) {
    return (WatchEvent<T>) event;
    }
    
    private void initWatchService() throws IOException {
    watcher = FileSystems.getDefault().newWatchService();
    keys = Collections.synchronizedMap(new HashMap<WatchKey, Path>());
    }
    
    private void registerTopLevelSrcFolder() throws IOException {
    for (Path dir : srcPaths) {
        try {
        // logger.print(logger.INFO, logger.PFR,
        // "registerTopLevelSrcFolder",
        // "Top level directory to be registered is " + dir);
        System.out.println("Top level directory to be registered is "
            + dir);
        register(dir);
        // doScan(dir);
        // scanAllFilesOnly(dir);
        } catch (AccessDeniedException e) {
        e.printStackTrace();
        } catch (NoSuchFileException e) {
        e.printStackTrace();
        }
    }
    }
    
    /**
     * Exception Register the given directory with the WatchService
     */
    private void register(Path dir) throws IOException {
    final String subModule = module + "register";
    
    File file = dir == null ? null : dir.toFile();
    if (file == null || !file.exists()) {
        return;
    }
    
    WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE,
        ENTRY_MODIFY);
    if (trace) {
    
        Path prev = keys.get(key);
        if (prev == null) {
        } else {
        if (!dir.equals(prev)) {
            addToScannedListOnDirRename(file, true);
        }
        }
    }
    keys.put(key, dir);
    }
    
    /**
     * On rename of a directory it adds all the child folders and files.
     *
     * @param dir
     * @throws PFRScanFailedException
     */
    /**
     * On rename of a directory it adds all the child folders and files.
     *
     * @param dir
     * @throws PFRScanFailedException
     */
    private void addToScannedListOnDirRename(File dir, boolean rename)
        throws IOException {
    // System.out.println("addToScannedListOnDirRename" + dir);
    String subModule = module + "addToScannedListOnDirRename";
    try {
    
        if (dir.isDirectory()) {
        if (!rename) {
            try {
            register(Paths.get(dir.getAbsolutePath()));
            } catch (NoSuchFileException e1) {
            // consume.
            }
        }
        File[] files = dir.listFiles();
        if (files == null) {
            return;
        }
        for (File file : files) {
            if (file == null) {
            continue;
            }
            // doScan(file);
            if (file.isDirectory()) {
            addToScannedListOnDirRename(file, rename);
            }
        }
        }
    
    } finally {
    
    }
    }
    
    boolean closed = false;
    private String uniqueFSName = "directoryWatcher";
    
    public void close() {
    if (closed) {
        return;
    }
    String subModule = module + "close";
    try {
        if (watcher != null) {
        watcher.close();
        }
    } catch (IOException e) {
    } finally {
        freeResources();
    }
    closed = true;
    }
    
    private void freeResources() {
    watcher = null;
    if (keys != null) {
        keys.clear();
    }
    // logger.print(logger.VERBOSE, logger.PFR,
    // "DirectoryWatcher-freeResources ",
    // "end of Directory Watcher. Freeing up resources");
    }
    
    private void DirectoryWatcherCore() {
    
    String subModule = module + "DirectoryWatcherCore";
    // enable trace after initial registration
    trace = true;
    for (;;) {
        // wait for key to be signalled
        try {
        WatchKey key = null;
        try {
            key = watcher.take();
        } catch (InterruptedException x) {
            x.printStackTrace();
            return;
        } catch (ClosedWatchServiceException x) {
            x.printStackTrace();
            return;
        }
        if (key == null) {
            System.out.println("key is nulllllllllllllllllllllll");
        }
        Path dir = keys.get(key);
        // System.out.println("**********" + dir);
        if (dir == null) {
            // logger.print(logger.ERROR, logger.PFR, subModule,
            // "WatchKey not recognized!!");
            continue;
        }
    
        for (WatchEvent<?> event : key.pollEvents()) {
            final WatchEvent.Kind kind = event.kind();
    
            if (kind == OVERFLOW) {
            logFileWriter.println("OVERFLOW");
            System.out
                .println("XXXXXXXXXXXXXXXXXXX----->>>OVERFLOW<<<--------XXXXXXXXXXXXXXXXXXX");
    
            // triggerFullScan();
    
            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);
            File childPath = child.toFile();
            File parent = dir.toFile();
    
            // logger.print(logger.VERBOSE2, logger.PFR, subModule,
            // event
            // .kind().name() + " filename "+name+" child " + child +
            // " parent "+dir + " watchable="+key.watchable());
    
            if (!childPath.getParentFile().getAbsolutePath()
                .equals(parent.getAbsolutePath())) {
            System.out
                .println("ERRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR");
            System.out.println(childPath.getParentFile()
                .getAbsoluteFile());
            System.out.println(parent.getAbsolutePath());
            }
    
            // System.out.println(event.kind().name() +
            // " name "+name+" child " + child + " dir "+dir);
            // if directory is created, and watching recursively, then
            // register it and its sub-directories
            if (kind == ENTRY_CREATE) {
            // System.out.println("created-" + child);
            logFileWriter.println("CREATE:" + child);
            try {
                if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
                try {
                    registerAll(child);
                    // addToScannedListOnDirRename(child.toFile(),
                    // false);
                } catch (NoSuchFileException ex) {
                    // logger.print(logger.VERBOSE, logger.PFR,
                    // moduleName,
                    // "Received ENTRY_CREATE and NoSuchFileException continuing from here "
                    // + ex+" for dir "+child);
                    continue;
                }
    
                }
            } catch (AccessDeniedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
                triggerFullScan();
                return;
            }
            }
    
            File file = child.toFile();
            if (kind == ENTRY_CREATE || kind == ENTRY_MODIFY) {
            // System.out.println("created/modify-" + child);
            logFileWriter.println("CREATE/MODIFY: " + child);
            try {
                // logger.print(logger.VERBOSE2, logger.PFR,
                // subModule, "Adding create event = " + fileInfo);
    
                filesList.add(file.getCanonicalPath());
                if (file.isDirectory()) {
    
                }
            } catch (Exception e) {
                triggerFullScan();
                return;
            }
            } else if (kind == ENTRY_DELETE) {
            logFileWriter.println("DELETE: " + child);
            deleteDir(file);
            }
        }
    
        // reset key and remove from set if directory no longer
        // accessible
        boolean valid = key.reset();
        if (!valid) {
            keys.remove(key);
    
            // all directories are inaccessible
            if (keys.isEmpty()) {
            break;
            }
        }
    
        } catch (Exception e) {
        e.printStackTrace();
        triggerFullScan();
    
        String failureCause = e.getMessage();
    
        return;
        } catch (Throwable e) {
    
        triggerFullScan();
        e.printStackTrace();
        return;
        }
    }
    }
    
    private void deleteDir(File file) {
    // TODO Auto-generated method stub
    
    }
    
    private void triggerFullScan() {
    // TODO Auto-generated method stub
    
    }
    
    /**
     * Register the given directory, and all its sub-directories, with the
     * WatchService.
     *
     * @throws PFRScanFailedException
     */
    private void registerAll(final Path start) throws Exception {
    // register directory and sub-directories
    walkFileTree(start);
    }
    
    private void walkFileTree(Path start) throws IOException {
    int retryCount = 0;
    int maxRetry = 5;
    
    String subModule = module + "walkFileTree";
    while (true) {
        try {
    
        if (start == null) {
            return;
        }
    
        Files.walkFileTree(start, SFRFileVisitor);
        break;
        } catch (AccessDeniedException adx) {
        retryCount++;
        if (retryCount == maxRetry) {
            throw adx;
        }
        File file = start.toFile();
        if (file == null || !file.exists()) {
            break;
        }
    
        waitFor(5000);
        continue;
        } catch (IOException iex) {
        retryCount++;
        if (retryCount == maxRetry) {
            throw iex;
        }
    
        waitFor(5000);
        continue;
        }
    }
    }
    
    public static void waitFor(int milliseconds) {
    try {
        Thread.sleep(milliseconds);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }
    
    /**
     * Process all events for keys queued to the watcher
     */
    @Override
    public void run() {
    Thread.currentThread().setName(uniqueFSName);
    try {
        DirectoryWatcherCore();
    } finally {
        freeResources();
    }
    }
    
    class FilesetSimpleFileVisitor extends SimpleFileVisitor<Path> {
    
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
        throws IOException {
        try {
        // doScan(file);
        } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        // logger.printStackTrace(logger.PFR,
        // "PFRScanFailedException-visitFile", e);
        }
        return FileVisitResult.CONTINUE;
    }
    
    @Override
    public FileVisitResult preVisitDirectory(Path dir,
        BasicFileAttributes attrs) throws IOException {
        String subModule = "preVisitDirectory";
        try {
        register(dir);
        // doScan(dir);
        return FileVisitResult.CONTINUE;
        } catch (NoSuchFileException e) {
        return FileVisitResult.SKIP_SUBTREE;
        } catch (Exception e) {
        e.printStackTrace();
        throw new IOException(e);
        }
    }
    }
    
    public void startDirectoryRegisterProcess() throws Exception {
    // registering all path
    String subModule = "-startDirectoryRegisterProcess-";
    // logger.print(logger.INFO, logger.PFR, subModule,
    // "Initaited registering process");
    long startTime = System.currentTimeMillis();
    
    for (Path dir : srcPaths) {
        // logger.print(logger.INFO, logger.PFR, subModule,
        // "Started registring directory" + dir);
        try {
        // registering sub directories
        File folder = dir.toFile();
        if (folder == null) {
            continue;
        }
    
        File[] listOfFiles = folder.listFiles();
        if (listOfFiles == null || listOfFiles.length == 0) {
            continue;
        }
        for (File file : listOfFiles) {
            if (file.exists() && file.isDirectory()) {
            try {
                registerAll(Paths.get(file.getCanonicalPath()));
            } catch (NoSuchFileException iox) {
                // consume NoSuchFileException exception
            }
    
            }
        }
    
        } catch (AccessDeniedException e) {
        // handleAccessDeniedException(e, true);
        e.printStackTrace();
        } catch (Exception e) {
        e.printStackTrace();
        // handleException(e, true);
        }
    }
    
    long registrationTime = System.currentTimeMillis() - startTime;
    }
    
    public static void testWatchDir(List<Path> dirs) throws Exception {
    
    final DirectoryWatcher dw = new DirectoryWatcher(dirs);
    Runnable runner = new Runnable() {
    
        @Override
        public void run() {
        while (true) {
            try {
            waitFor(10 * 1000);
    
            System.out.println("Pending file count="
                + filesList.size());
    
            findFilesPresentOnDiskButNotInList();
            System.out
                .println("----------------------------------");
            } catch (Exception e) {
            e.printStackTrace();
            }
        }
        }
    };
    new Thread(runner).start();
    
    dw.startDirectoryRegisterProcess();
    }
    
    /**
     * Checks if the file is present on Disk but not on the list which was
     * created by the events that was received by Directory Watcher
     *
     * @throws Exception
     */
    public static void findFilesPresentOnDiskButNotInList() throws Exception {
    List<String> missedFiles = new ArrayList<String>();
    
    for (Path src : srcPaths) {
        findDiff(src.toFile(), missedFiles);
    }
    if (missedFiles.size() == 0) {
        System.out.println("No files are missed");
    } else {
        System.out.println("findFilesPresentOnDiskButNotInList");
        System.out.println("The files that have been missed are");
        for (String filePath : missedFiles) {
        System.out.println(filePath);
        }
    }
    
    System.out.println("###################################");
    }
    
    public static void findDiff(File folder, List<String> missedFiles)
        throws Exception {
    
    File[] files = folder.listFiles();
    if (files != null && files.length > 0) {
        for (File child : files) {
        if (!filesList.contains(child.getCanonicalPath())) {
            missedFiles.add(child.getCanonicalPath());
        }
        if (child.isDirectory()) {
            findDiff(child, missedFiles);
        }
        }
    }
    }
    
    public static void main(String[] args) throws Exception {
    
    System.out.println("started");
    
    List<String> pathNames = new ArrayList<String>();
    List<Path> dirPaths = new ArrayList<Path>();
    // if two arguments are passed to the main function then
    // we assume that the first argument represents the directory where the
    // files and folders are getting created. And the second argument is for
    // the
    // path to the log file.
    // else we ask the user to enter input through command line
    if (args.length < 2) {
        getUserInput(pathNames);
    } else {
        // arg[0] is the folder to be watched
        pathNames.add(args[0]);
        // arg[1] is the log file that has been created
        LOG_FILE_PATH = args[1];
    }
    // code for log file
    System.out.println("The log file is " + LOG_FILE_PATH);
    new File(LOG_FILE_PATH).deleteOnExit();
    new File(LOG_FILE_PATH).createNewFile();
    logFileWriter = new PrintWriter(LOG_FILE_PATH);
    
    for (String path : pathNames) {
        dirPaths.add(Paths.get(path));
    }
    
    testWatchDir(dirPaths);
    
    System.out.println("ended");
    }
    
    private static void getUserInput(List<String> pathNames) {
    System.out
        .println("please enter the path of directory to be watched for events");
    Scanner input = new Scanner(System.in);
    
    if (input.hasNext()) {
        pathNames.add(input.nextLine());
    }
    
    System.out.println("Please enter the log file path");
    if (input.hasNext()) {
        LOG_FILE_PATH = input.nextLine();
    }
    
    }
    
    }
    

0 个答案:

没有答案