WatchService. WatchEvent .context() метод возвращает непоследовательный относительный путь для файла в ENTRY_MODIFY (goutputstream-####, ОС Linux)
В этом коде я надеюсь обновить HashMap самой последней версией содержимого заданного пути, указав в качестве ключа абсолютный путь в виде строки. Проблема в том, что WatchEvent
"s .context()
Метод дает мне разные относительные пути для одного и того же файла на каждом событии.
Вот фрагмент кода:
else if(event.kind()==StandardWatchEventKinds.ENTRY_MODIFY)
{
/*Variable path is a Path of "//workspaces", set earlier.*/
Path oldfilepath=path.resolve((Path)event.context()); /*problem line*/
String oldfilepathstring = oldfilepath.toString();
FileReader oldIn = new FileReader(oldfilepathstring);
BufferedReader br = new BufferedReader(oldIn);
String line;
List<String> newfiletext=new LinkedList<>();
while((line = br.readLine())!=null)
newfiletext.add(line);
List<String> previousText=new LinkedList<>();
if((previousText = fileMappings.get(oldfilepathstring))!= null)
{
System.out.println("previoustext:\n"+previousText);
System.out.println("newfiletext:\n"+newfiletext);
}
fileMappings.put(oldfilepathstring, newfiletext);
System.out.println(fileMappings.keySet()+"\n"+fileMappings.values());
}
}
А вот пример вывода после изменения файла b.txt
в просматриваемой директории от содержимого "abc" до "abc
123"
Обратите внимание, что все это происходит просто путем открытия файла /workspaces/b.txt (который уже существует) и изменения его содержимого.):
бежать: ENTRY_CREATE:.goutputstream-BRC1HX ENTRY_MODIFY:.goutputstream-BRC1HX [/Workspaces/.goutputstream-BRC1HX] [[]] ENTRY_MODIFY:.goutputstream-BRC1HX previoustext: [] newfiletext: [ABC] [/Workspaces/.goutputstream-BRC1HX] [[ABC]] ENTRY_CREATE:b.txt~ ENTRY_CREATE:b.txt ENTRY_CREATE:.goutputstream-MFJ6HX ENTRY_MODIFY:.goutputstream-MFJ6HX [/workspaces/.goutputstream-MFJ6HX, /workspaces/.goutputstream-BRC1HX] [[], [abc]] ENTRY_MODIFY:.goutputstream-MFJ6HX previoustext: [] newfiletext: [abc, 123] [/workspaces/.goutputstream-MFJ6HX, /workspaces/.goutputstream-BRC1HX] [[abc, 123], [abc]] ENTRY_CREATE:b.txt~ ENTRY_CREATE:b.txt
Интересная линия Path oldfilepath=path.resolve((Path)event.context());
Обратите внимание, как oldfilepath
разрешил в "/workspaces/.goutputstream-MFJ6HX", а затем "/workspaces/.goutputstream-BRC1HX" для того же файла.
event.context()
возвращает разные пути для одного и того же файла после каждой модификации. Это проблема Linux или Java, и как именно я получу стандартный относительный путь (в данном случае это будет "b.txt") для этого файла?
Кажется, что когда я выполняю модификацию, я получаю последовательность событий создания / изменения / создания, и ENTRY_CREATE
с правильным именем файла, ENTRY_MODIFY
у меня есть временный дескриптор (я предполагаю, что временная версия файла используется между сохранениями). Мне нужно иметь возможность зафиксировать изменение файла и извлечь правильное имя файла из этого события.
Я понимаю, что моя файловая система может выполнять создание и обработку временного файла под капотом, пока я просто открываю, изменяю и сохраняю файл, но как именно я могу извлечь правильное имя файла из временного файла, который указывает событие ENTRY_MODIFY
дает мне? Есть ли какой-то метод для группировки событий, относящихся к этой модификации, чтобы я мог просто найти вмещающий ENTRY_CREATE
и получить имя файла от этого? Или как-то пройти вверх через стек вызовов, ведущих к этому ENTRY_CREATE
?
Я могу увидеть имя файла во вложении ENTRY_CREATE
события, окружающие друг ENTRY_MODIFY
, но я надеюсь, что есть более элегантный способ сделать это, чем каким-либо образом (получить последнее событие, которое не было ENTRY_MODIFY
, а затем получить .context()
От этого.)
Спасибо!
1 ответ
Я столкнулся с тем же вопросом. Я думаю, что это не имеет никакого отношения к проблемам Linux или Java. Это просто способ, которым редактор b.txt (я полагаю, gedit) обрабатывает эту вещь.
После сохранения
создает новый временный файл ".goutputstream-xxxx" с каким-то случайным xxxx (который вы видите),
записывает новое содержимое в этот файл (видоизменяемое вами изменение),
переименовывает исходный файл в b.txt~ (то, что вы видите),
и переименовывает временный файл в b.txt (создание, которое вы видите)
Поэтому я думаю, что вам нужно следить за ENTRY_MODIFY и ENTRY_CREATE в отношении b.txt, чтобы действительно увидеть все модификации файла.
У меня такая же проблема. Я использую фильтр, чтобы исключить эту проблему. Например: мне нужны все файлы в пути /home/user/data/in;
Files.walk(Paths.get( System.getProperty("user.home").concat("/data/in")))
.map(Path::toString)
.filter(path -> ! path.endsWith("/in"))
.filter(path -> ! path.startsWith(".goutputstream"))
.collect(Collectors.toList());
Это исправление для меня.