Подтвердить что ты не робот

Как узнать, когда файл "Готово" копируется в наблюдаемый каталог?

Я использую WatchService API для просмотра каталога и получения ENTRY_CREATE события, когда пользователь начинает копировать файл в каталог. Файлы, с которыми я работаю, могут быть большими, и я хотел бы знать, когда копия будет закончена. Есть ли встроенный java API, который я могу использовать для этого, или мне лучше всего отслеживать размер созданных файлов и начать обработку, когда размер перестает расти?

EDIT: Вот мой пример кода:

package com.example;

import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

public class Monitor {
    public static void main(String[] args) {
        try {
            String path = args[0];

            System.out.println(String.format( "Monitoring %s", path  ));
            WatchService watcher = FileSystems.getDefault().newWatchService();
            Path watchPath = FileSystems.getDefault().getPath(path);

            watchPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY);

            while (true) {
                WatchKey key = watcher.take();
                for (WatchEvent<?> event: key.pollEvents()) {
                    Object context = event.context();
                    System.out.println( String.format( "Event %s, type %s", context, event.kind() ));

                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Что выдает этот вывод:

Monitoring /Users/ericcobb/Develop/watch
Event .DS_Store, type ENTRY_MODIFY
Event 7795dab5-71b1-4b78-952f-7e15a2f39801-84f3e5daeca9435aa886fbebf7f8bd61_4.mp4, type ENTRY_CREATE
4b9b3361

Ответ 1

Когда запись будет создана, вы получите событие ENTRY_CREATE. Для каждой последующей модификации вы получите ENTRY_MODIFY событие. Когда копирование завершено, вы будете уведомлены с помощью ENTRY_MODIFY.

Ответ 2

  • Я думаю, что наиболее распространенный способ сделать это - скопировать файл во временный каталог на том же разделе, а затем переместить его в контролируемый каталог с помощью команды атомарного перемещения.
  • Возможно, решение также может быть достигнуто путем игры с отметками времени файлов

Однако оба этих решения должны быть реализованы в приложении для написания. Я думаю, вы не можете точно сказать из приложения для чтения.

Ответ 3

Это библиотека, которую мы используем сегодня:

https://github.com/levelsbeyond/jpoller

Это вилка проекта с открытым исходным кодом, которого автор уже не поддерживает. Мы исправили несколько ошибок, и сегодня используем его в производстве.

Он работает, проверяя размер файлов в каталоге и рассматривает сделанный файл (готовый к обработке) после того, как размер файла перестает расти в течение определенного периода времени.

Ответ 4

Возможно, вы можете сказать, пытаясь получить доступ на запись к файлу, но это зависит от двух факторов и требует исследований:

  • Приложение для записи должно получить исключительное разрешение на запись в файл и не должно закрывать файл до его завершения.
  • Должна быть возможность проверить это на Java. Я бы попробовал, открытие файла как FileChannel для доступа WRITE вызывает исключение, если файл по-прежнему заблокирован для записи другой программой. К несчастью, Javadoc не входит в подробности об этом.

Ответ 5

File file = child.toAbsolutePath().toFile();
if(file.isFile() && file.isWrite())
{
}

Возможно, это будет способ узнать, чего вы хотите, но не в инструкции while.

Он будет работать, когда вы действительно получите доступ к файлу.

Ответ 6

Единственный допустимый вариант, чтобы гарантировать, что никакой другой процесс не записывает в файл больше, - это успешно получить блокировку записи в файле. Хотя немного неуклюжий, вы можете использовать FileChannel и FileLock для этой цели

try(FileChannel ch = FileChannel.open(p, StandardOpenOption.WRITE);
    FileLock lock = ch.tryLock()){

    if(lock == null) {
        //no lock, other process is still writing            
    } else {
        //you got a lock, other process is done writing
    }
 } catch (IOException e) {
     //something else went wrong
 }

Вы также можете получить блокировку с помощью ch.lock(), который является блокирующим вызовом. Но поскольку события ENTRY_MODIFY непрерывно генерируются при записи файла, вы также можете использовать tryLock и ждать следующего события.