How to wait on file creation

2020-04-18 06:49发布

My situation is as following: I got a Java program, wich starts a perl script. The Perl script is generating a file, on which Java should continue working. As by now, i had set a

Thread.sleep(3000);

to let Java wait for the file to be finished. I was looking for an more elegant way to let Java check if the file exists and continue then. My last try was

Boolean waitforfile = true;  
while(waitforfile){
       File f = new File(pathtofile);
       if(f.exists() && !f.isDirectory()) { waitforfile=false; }
       } 

But that one will get me stuck in a never ending loop. Is there any way else to do it?

Update : On Suggestion, tried, process,WaitFor(); In

    public static String syscall(String call){
    String out = "";
    try {
    String line;
    Process p = Runtime.getRuntime().exec(call);
    BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while ((line = input.readLine()) != null) {
      out=out+"\n"+line;
    }
    input.close();
    p.waitFor();
    } catch (Exception e) {
        System.out.println(e);
    }

    return out;
}

This one did not wait on my perl process to be closed.

标签: java file io
2条回答
女痞
2楼-- · 2020-04-18 07:41

As @peter-lawrey has mentioned, the correct way to go is java.nio.file.WatchService.

The following is a simple implementation for the specific (but common) case of waiting the creation of a file. This static method returns the basic file attributes of the target file (creationTime is among them), or null if the file did not show up.

public static BasicFileAttributes awaitFile(Path target, long timeout) 
    throws IOException, InterruptedException
{
    final Path name = target.getFileName();
    final Path targetDir = target.getParent();

    // If path already exists, return early
    try {
        return Files.readAttributes(target, BasicFileAttributes.class);
    } catch (NoSuchFileException ex) {}

    final WatchService watchService = FileSystems.getDefault().newWatchService();
    try {
        final WatchKey watchKey = targetDir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
        // The file could have been created in the window between Files.readAttributes and Path.register
        try {
            return Files.readAttributes(target, BasicFileAttributes.class);
        } catch (NoSuchFileException ex) {}
        // The file is absent: watch events in parent directory 
        WatchKey watchKey1 = null;
        boolean valid = true;
        do {
            long t0 = System.currentTimeMillis();
            watchKey1 = watchService.poll(timeout, TimeUnit.MILLISECONDS);
            if (watchKey1 == null) {
                return null; // timed out
            }
            // Examine events associated with key
            for (WatchEvent<?> event: watchKey1.pollEvents()) {
                Path path1 = (Path) event.context();
                if (path1.getFileName().equals(name)) {
                    return Files.readAttributes(target, BasicFileAttributes.class);
                }
            }
            // Did not receive an interesting event; re-register key to queue
            long elapsed = System.currentTimeMillis() - t0;
            timeout = elapsed < timeout? (timeout - elapsed) : 0L;
            valid = watchKey1.reset();
        } while (valid);
    } finally {
        watchService.close();
    }

    return null;
}
查看更多
做个烂人
3楼-- · 2020-04-18 07:46

A better way is to write the file to a temporary file name like myscript.pl.tmp and rename it when you are finished. As rename is atomic, you won't see it in an incomplete state.

BTW You can use the WatchService to be notified when a file appears. Watching a Directory for Changes

查看更多
登录 后发表回答