Я реализовал наблюдатель файлов, но заметил, что просмотрщик файлов java nio не генерирует события для копирования файлов на сопоставленные диски. Например, я запустил наблюдателя файлов в Unix для просмотра локального каталога (/sharedfolder
), который отображается в окнах (H:\
), а затем я поместил файл в этот каталог (H:\
), но наблюдатель не генерировал никакого события. Теперь, если я запускаю наблюдателя файлов в окнах, чтобы отслеживать подключенный диск (H:\
), который ссылается на путь unix (/sharedfolder
), а из unix я помещаю файл в эту папку, наблюдатель файла идентифицирует изменение и генерирует мероприятие. Это похоже на ошибку, или может быть, я что-то пропустил, какие-то мысли?
Java WatchService не генерирует события во время просмотра подключенных дисков
Ответ 1
У меня та же проблема, когда я пытаюсь посмотреть, как установлен общий доступ к Windows через CIFS. Кажется, невозможно получить события файловой системы для монтирования CIFS.
В Linux-реализации NIO FileWatcher для Linux используется inotify. Inotify - это подсистема ядра Linux, которая замечает изменения файловой системы, которая отлично работает для локальных каталогов, но, очевидно, не для монтирования CIFS.
В Oracle, похоже, не является высоким приоритетом исправление этой ошибки. (Это их ответственность? Больше проблем с ОС...)
JNotify также использует inotify в системах Linux, так что это тоже не вариант.
Таким образом, мониторинг подключенных дисков, к сожалению, ограничивается опросами:
- Apache VFS DefaultFileMonitor для опроса каталогов (смонтированный общий ресурс)
- File Poller на основе стандартного Java API.
- Пользовательский файл Poller с jCIFS (поэтому общий ресурс не нужно монтировать на хосте)
Я, наверное, попробую Apache VFS Monitor, потому что он обнаруживает создание файлов, обновления и удаление из коробки. Требуется смонтировать общий ресурс, но это дает ОС ответственность за соединения CIFS, а не мое приложение.
Ответ 2
Функция просмотра файлов в JDK зависит от платформы, поскольку она использует собственные библиотеки, чтобы она могла вести себя по-разному на разных платформах. Я удивлен, что он работает на сетевых дисках вообще - Windows должна опросить подключенные к сети диски для изменений, в то время как Linux не делает (по праву, поэтому я должен сказать).
Обычно такой мониторинг выполняется в ядре ОС, который, очевидно, имеет знания о том, какие файлы были изменены/созданы локально, но нет никаких простых способов для ОС знать, что происходит на сетевом диске, поскольку оно не имеет исключительного контроля над он.
Ответ 3
У меня была та же проблема. Я решил это, создав новый поток в главном классе и периодически касаясь файлов, чтобы сработало новое событие изменения.
Пример опроса dir на каждые 10 секунд делает прикосновение.
package com.ardevco.files;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.List;
public class Touch implements Runnable {
private Path touchPath;
public Touch(Path touchPath) {
this.touchPath = touchPath;
this.checkPath = checkPath;
}
public static void touch(Path file) throws IOException {
long timestamp = System.currentTimeMillis();
touch(file, timestamp);
}
public static void touch(Path file, long timestamp) throws IOException {
if (Files.exists(file)) {
FileTime ft = FileTime.fromMillis(timestamp);
Files.setLastModifiedTime(file, ft);
}
}
List<Path> listFiles(Path path) throws IOException {
final List<Path> files = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
for (Path entry : stream) {
if (Files.isDirectory(entry)) {
files.addAll(listFiles(entry));
}
files.add(entry);
}
}
return files;
}
@Override
public void run() {
while (true) {
try {
for (Path path : listFiles(touchPath)) {
touch(path);
}
} catch (IOException e) {
System.out.println("Exception: " + e);
}
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
System.out.println("Exception: " + e);
}
}
}
}
Ответ 4
У меня были аналогичные проблемы с Python script просмотр содержимого файла журнала в удаленной директории Windows.
Вот мой ответ.
При сопоставлении удаленного диска с Unix в /etc/fstab
используйте //xxx.xxx.xxx.xxx/shareddrive /media/shareddrive cifs username=xxxx,password=xxxx,**directio** 0 0
Вы можете использовать файл учетных данных, чтобы избежать использования пароля в виде обычного текста.
Команда может меняться в зависимости от версии unix, это было проверено под debian. Он должен работать по назначению. Можете ли вы сказать мне, работает ли это? Я планирую реализовать один и тот же материал на Java, поэтому ответ может быть полезен и мне.
Ответ 5
Я тоже столкнулся с этим и пришел к такому же выводу, что и все остальные (CIFS + inotify = no go).
Однако, поскольку мой рабочий процесс зависел как от удаленных монтировок, так и от инструментов автоматической компиляции, которые полагаются на inotify, я закончил создание (довольно отчаянное и хакерское) решение, которое в основном просто использует опрос, чтобы следить за изменениями, а затем затрагивает те же файлы снова на смонтированной стороне, которая, похоже, запускает события inotify. Это не мой самый гордый момент.
Сказав это, он работает, поэтому наслаждайтесь: http://github.com/rubyruy/watchntouch