Reputation: 454
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.
Upvotes: 3
Views: 14803
Reputation: 51
Check whether the file exists (Files.exists()) in the directory or not using while loop. Continue the loop till it returns False, and get out of the loop once it finds the file in the directory.
Upvotes: 0
Reputation: 1585
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;
}
Upvotes: 5
Reputation: 533492
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
Upvotes: 6