如何等待文件创建
How to wait on file creation
我的情况如下:
我有一个 Java 程序,它启动了一个 perl 脚本。
Perl 脚本正在生成一个文件,Java 应该可以在该文件上继续工作。
到目前为止,我已经设置了一个
Thread.sleep(3000);
让Java等待文件完成。
我一直在寻找一种更优雅的方式让 Java 检查文件是否存在然后继续。我最后一次尝试是
Boolean waitforfile = true;
while(waitforfile){
File f = new File(pathtofile);
if(f.exists() && !f.isDirectory()) { waitforfile=false; }
}
但是那个会让我陷入一个永无止境的循环。
还有其他办法吗?
更新:
根据建议,尝试过,处理,WaitFor();
在
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;
}
这个没有等待我的 perl 进程关闭。
更好的方法是将文件写入临时文件名,如myscript.pl.tmp
,完成后重命名。由于重命名是原子的,您不会看到它处于未完成状态。
顺便说一句,您可以使用 WatchService 在文件出现时收到通知。 Watching a Directory for Changes
正如@peter-lawrey 所提到的,正确的方法是 java.nio.file.WatchService
。
以下是等待创建文件的特定(但常见)情况的简单实现。这个静态方法 returns 目标文件的基本文件属性(creationTime
是其中之一),如果文件没有出现,则 null
。
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;
}
我的情况如下: 我有一个 Java 程序,它启动了一个 perl 脚本。 Perl 脚本正在生成一个文件,Java 应该可以在该文件上继续工作。 到目前为止,我已经设置了一个
Thread.sleep(3000);
让Java等待文件完成。 我一直在寻找一种更优雅的方式让 Java 检查文件是否存在然后继续。我最后一次尝试是
Boolean waitforfile = true;
while(waitforfile){
File f = new File(pathtofile);
if(f.exists() && !f.isDirectory()) { waitforfile=false; }
}
但是那个会让我陷入一个永无止境的循环。 还有其他办法吗?
更新: 根据建议,尝试过,处理,WaitFor(); 在
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;
}
这个没有等待我的 perl 进程关闭。
更好的方法是将文件写入临时文件名,如myscript.pl.tmp
,完成后重命名。由于重命名是原子的,您不会看到它处于未完成状态。
顺便说一句,您可以使用 WatchService 在文件出现时收到通知。 Watching a Directory for Changes
正如@peter-lawrey 所提到的,正确的方法是 java.nio.file.WatchService
。
以下是等待创建文件的特定(但常见)情况的简单实现。这个静态方法 returns 目标文件的基本文件属性(creationTime
是其中之一),如果文件没有出现,则 null
。
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;
}