Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell when a File is "Done" copying into a watched Directory?

Tags:

java

file

path

I'm using the WatchService API to watch a directory, and getting ENTRY_CREATE events when a user starts copying a file into the directory. The files I'm working with can be large, though, and I'd like to know when the copy is finished. Is there any built in java API I can use to accomplish this, or am I best off to just keep track of the created files' size and start processing when the size stops growing?

EDIT: Here is my example code:

package com.example;

import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

public class Monitor {
    public static void main(String[] args) {
        try {
            String path = args[0];

            System.out.println(String.format( "Monitoring %s", path  ));
            WatchService watcher = FileSystems.getDefault().newWatchService();
            Path watchPath = FileSystems.getDefault().getPath(path);

            watchPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY);

            while (true) {
                WatchKey key = watcher.take();
                for (WatchEvent<?> event: key.pollEvents()) {
                    Object context = event.context();
                    System.out.println( String.format( "Event %s, type %s", context, event.kind() ));

                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Which Produces this output:

Monitoring /Users/ericcobb/Develop/watch
Event .DS_Store, type ENTRY_MODIFY
Event 7795dab5-71b1-4b78-952f-7e15a2f39801-84f3e5daeca9435aa886fbebf7f8bd61_4.mp4, type ENTRY_CREATE
like image 309
eric Avatar asked Jul 29 '13 20:07

eric


2 Answers

When an entry is created, you will get an ENTRY_CREATE event. For every subsequent modification, you will get an ENTRY_MODIFY event. When copying is completed, you will be notified with an ENTRY_MODIFY.

like image 115
Jeffrey Avatar answered Sep 28 '22 04:09

Jeffrey


The only valid option to ensure, no other process is writing to the file anymore is to successfully obtain a Write lock on the file. Although a bit clumsy, you could use FileChannel and FileLock for that purpose

try(FileChannel ch = FileChannel.open(p, StandardOpenOption.WRITE);
    FileLock lock = ch.tryLock()){

    if(lock == null) {
        //no lock, other process is still writing            
    } else {
        //you got a lock, other process is done writing
    }
 } catch (IOException e) {
     //something else went wrong
 }

You could as well obtain a lock using ch.lock() which is a blocking call. But since ENTRY_MODIFY events are continously generated when the file is being written to, you can as well use tryLock and wait for the next event.

like image 35
Gerald Mücke Avatar answered Sep 28 '22 04:09

Gerald Mücke