#java
#java
Вопрос:
Я использую службу наблюдателя для мониторинга каталога в Windows. Если в файл внесено изменение, я бы хотел записать временную метку в тот же файл. Конечно, это еще одна модификация каталога, и затем наблюдатель снова обрабатывает событие. Есть ли способ приостановить работу наблюдателя, чтобы я мог обновить файл, а затем перезапустить его, чтобы он мог дождаться следующего события?
Возможно, есть лучшее предложение???
package net.codejava.io;
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 java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.sql.Timestamp;
import java.util.Date;
public class DirectoryWatchDemo {
static String logfile = "C:/Temp/log.txt";
volatile static boolean suspended = false;
public static void main(String[] args) {
try {
WatchService watcher = FileSystems.getDefault().newWatchService();
Path dir = Paths.get("C:/Temp/");
dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
// System.out.println("Watch Service registered for dir: "
// dir.getFileName());
while (true) {
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException ex) {
return;
}
if (!suspended) {
resume();
} else {
updateFile();
suspend();
}
if (key.isValid())
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path fileName = ev.context();
System.out.println(kind.name() ": " fileName);
}
boolean valid = key.reset();
if (!valid) {
System.out.println("Watch service invalid");
break;
}
}
} catch (IOException ex) {
System.err.println(ex);
}
}
private static void suspend() {
suspended = false;
}
private static void resume() {
suspended = true;
}
public static void updateFile() {
try {
File outfile = new File(logfile);
if (!outfile.exists()) {
System.out.println("No file exists...writing a new file");
outfile.createNewFile();
}
FileWriter fw = new FileWriter(outfile.getAbsoluteFile(), true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("TimeStamp: " new Timestamp(new java.util.Date().getTime()).toString() "rn");
bw.flush();
bw.close();
System.out.println("done");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ответ №1:
Вам нужно прервать поток, который использует службу наблюдения, потому что это единственный способ выйти из watcher.take()
него. Пример с потоками старой школы:
public void start() {
thread = new Thread(directoryWatchDemo::watch);
thread.start();
}
public void pause() throws InterruptedException {
if (thread.isAlive()) {
thread.interrupt();
thread.join();
}
}
Смотрите ExecutorService, например Executors.newSingleThreadExecutor() и Future.cancel() для большей гибкости.
В качестве альтернативы, вы можете take()
все события и игнорировать их на основе volatile boolean
.
Комментарии:
1. Можете ли вы подробнее рассказать о методе volatile Boolean? Это нужно было бы игнорировать непосредственно перед обновлением файла с метки времени, а затем снова включить. Извините, я новичок в этом…
2. @RLange Конечно. Вы объявляете
boolean volatile suspended = false
, и два методаsuspend()
, иresume()
которые устанавливают переменную. Сразу послеwatcher.take()
проверки значения и, если значение suspended равно true,continue
ожидание следующего изменения. Другой (не наблюдающий) поток, который обновит файл и установит временные метки, может контролировать, какие изменения будут эффективно обрабатываться, вызывая два метода.3. @RLange Если у вас всегда есть два изменения в паре, вы также можете подсчитать изменения и проверить, является ли текущее изменение нечетным или четным; или используйте Instant, а затем обрабатывайте изменения только тогда, когда произошло другое (недавнее) изменение.
4. Спасибо, Штеффен. Все еще работаю над первым предложением. Проблема заключается в том, что при изменении добавляется более одной временной метки. Я не совсем уверен, что вы говорите в своем втором предложении. «два изменения в паре»?
5. @RLange Ну, может быть, я неправильно понял вашу проблему. Я подумал, что вы изменяете содержимое файла (которое обновляет временную метку), а затем, через некоторое время, загружаете
touch
файл и снова обновляете mtime. Вы хотите начать обработку только после второго изменения послеtouch
. Если я ошибаюсь, пожалуйста, уточните свой вопрос.