Наблюдение за папкой с помощью WatchService и Selector

 
 
 
Сообщения:19
Вот тут Watching a Directory есть дока как следить за изменениями папке.
Я сделал. Работает.
public void run(){
		 // создаем новый Watch Service
		 try {
		 	watcher = FileSystems.getDefault().newWatchService();
		 } catch (IOException e) {
	 		e.printStackTrace();
	 	 }
		// указываем на директорию
		Path dir = Paths.get(directory);
		WatchKey key;
		try {
			key = dir.register(watcher,ENTRY_CREATE,ENTRY_MODIFY);
		} catch (IOException x) {
			// сообщение об ошибке если директория не найдена
			System.err.println(x );
		}

		// в цикле ожидаем сигнала
		for (;;) {
			// wait for key to be signaled
			try {
				key = watcher.take(); //Тут поток останавливается и наблюдает за директорией
			} catch (InterruptedException x) {
				return;
			}
			for (WatchEvent<?> event: key.pollEvents()) {
				WatchEvent.Kind<?> kind = event.kind();
                ...
				WatchEvent<Path> ev = (WatchEvent<Path>)event;
                // вот тут отслеживаем изменения в папке
                Path filename = ev.context();

                //ВОТ СЮДА НАДО ПРИПАЯТЬ КОД ИЗ ВТОРОГО ЛИСТИНГА
                //ЧТОБЫ С ПОМОЩЬЮ СЕЛЕКТОРА ОТСЛЕЖИВАТЬ КОНЕЦ КОПИРОВАНИЯ ФАЙЛА
                // а пока просто
                System.out.println("      " + filename);


			}
			boolean valid = key.reset();
			if (!valid) {
				break;
			}
		}
	}

Когда файлы копируются сторонним ПО в папку, этот код замечает следующее: факт появления (ENTRY_CREATE) нового файла. Если файл маленький то все прекрасно, можно сразу с ним что-то делать. Если файл большой, то приходит другое событие - ENTRY_MODIFY и ясно почему, ведь в файл дописывается следующая порция данных. Но когда процесс завершен, то никаких событий не возникает. Получается я не могу отловить завершение копирования.

На одном из форумов советовали:
Quote:
насколько я понимаю, операция закрытия файла должна ловиться через NIO селектором как SelectionKey.OP_READ, при этом вычитается -1.

я так думаю потому, что тут ru.wikipedia.org/wiki/Epoll написано, что еполлу не важно с чем он рабтает - с сокетом или с файлом.

То есть получается, что можно ловить появившиеся файлы, селектором вешать на них событие SelectionKey.OP_READ, по мере появлния данных вычитывать их, и когда прочтем -1, то это есть конец файла.

Жирным шрифтом, как бы предлагается решение. Стал смотреть что-такое селекторы.
Нашел это где собственно тоже есть пример.
void go(){
		try {
			Selector selector = Selector.open();
		    SelectableChannel channel = null;
    		if (channel != null) {
	    		SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
		    }
			while(true) {
				int readyChannels = selector.select();
				if(readyChannels == 0) continue;
			Set<SelectionKey> selectedKeys = selector.selectedKeys();
			Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
			while(keyIterator.hasNext()) {
				SelectionKey key = keyIterator.next();
				if(key.isAcceptable()) {
					System.out.println(" a connection was accepted by a ServerSocketChannel.");
				} else if (key.isConnectable()) {
					System.out.println("  a connection was established with a remote server.");
				} else if (key.isReadable()) {
					System.out.println(" a channel is ready for reading");
				} else if (key.isWritable()) {
					System.out.println(" a channel is ready for writing");
				}
				keyIterator.remove();
			}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


Но как припаять это к первому листингу? Вобщем глобальный вопрос, как отслеживать завершение копирования? Или менее глобальный как с помощью селектора "прицепиться" к файлу и отследить процесс завершение копирования? Или более конкретный, как соединить эти 2 листинга, что бы выполнялась задача.
 
 
Сообщения:18
Конец копирования файла предлагаю отслеживать следующим образом:
(кусок кода для в ставки в первый листинг)
Path fullFileName = dir.resolve(filename); // полный путь к файлу

while(true){
    try(Stream<String> stream = Files.lines(fullFuleName)){
        System.out.println("Файл готов к обработке!");
        break; 
    }catch(IOException ex){
        System.out.println("Файл занят!");
        continue;
    }
}

С Уважением, Павел!
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет