Java: WatchService получает информацию перед копированием контента
Я попытался скопировать и вставить очень маленький файл в папку, которая отслеживается службой наблюдения. Первый раз работает отлично, но при всех следующих действиях копирования и вставки я получаю исключение, что другой процесс уже обрабатывает файл. С помощью экспериментов я обнаружил, что мой сервис информируется, когда Windows создает файл, а не когда его содержимое копируется. Если я заблокирую файл, Windows не сможет скопировать данные, и файл будет пуст. С другой стороны, если я перемещаю файл в каталог, все работает нормально.
Это ошибка в Windows? Я не смог протестировать его на рабочей станции Mac или Linux. Или, может быть, я был просто неспособен. Любая помощь приветствуется.
Мой код выглядит следующим образом:
try (WatchService watchService = importPath.getFileSystem().newWatchService()) {
importPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
handleExistingFiles();
try {
do {
WatchKey watchKey = watchService.take();
if (!watchKey.isValid()) {
continue;
}
boolean hasCreationEvents = false;
for (WatchEvent<?> event : watchKey.pollEvents()) {
hasCreationEvents |= event.kind().equals(StandardWatchEventKinds.ENTRY_CREATE);
}
watchKey.reset();
if (hasCreationEvents) {
handleNewFiles();
}
}
while (!Thread.currentThread().isInterrupted());
}
catch (InterruptedException ignoredEx) {
Thread.currentThread().interrupt();
}
}
1 ответ
Операция копирования не всегда атомарна.
С атомарным копированием (или перемещением) вы получите одно событие ENTRY_CREATE, и файл, на который ссылается событие, будет завершен и доступен для чтения.
Если копия не является атомарной, вы получите событие ENTRY_CREATE при создании файла, а затем вы получите одно или несколько событий ENTRY_MODIFY во время записи файла операцией копирования.
Нет простого способа определить, когда операция копирования закончила запись в файл и выпустила его. В зависимости от операционной системы и файловой системы вы можете получить FileNotFoundException при попытке открыть файл для чтения, когда он заблокирован операцией копирования, или вы можете успешно открыть файл, но вы получите частичное содержимое, когда фактически прочитаете его.
Вам нужно будет реализовать некоторые эвристические методы, например, попытаться прочитать файл сразу после ENTRY_CREATE и перенастроить чтение на более позднее время, если первоначальное чтение не удалось.