Как узнать, выполняется ли копирование файлов/завершено в java (1.6)

Я пишу утилиту мониторинга каталога в java (1.6), используя опрос с определенными интервалами, используя lastModified длинное значение как указание на изменение. Я обнаружил, что, когда мой интервал опроса мал (в секундах), а скопированный файл большой, событие изменения запускается до фактического завершения копирования файлов.

Я хотел бы знать, есть ли способ найти статус файла, например, в пути, завершить и т.д.

Среды: Java 1.6; как ожидается, будет работать с окнами и Linux.

Ответы

Ответ 1

Есть два подхода, которые я использовал в прошлом, которые являются агностиками платформы.

1/Это было для FTP-передач, где я контролировал то, что было поставлено, поэтому оно не может быть непосредственно релевантным.

В принципе, все, что помещается в файл file.txt, будет, когда оно закончено, также поместит небольшой (возможно, нулевый) фиктивный файл под названием file.txt.marker (например).

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

2/Неизменная продолжительность.

Попросите программу вашего монитора ждать, пока файл не будет изменен в течение N секунд (где N гарантированно гарантированно будет достаточно большим, чтобы файл был закончен).

Например, если размер файла не изменился за 60 секунд, у него есть хороший шанс.

Там балансирующий акт между тем, что мы не думаем, что файл закончен только потому, что на нем нет активности, и ждать, когда он будет закончен, прежде чем вы сможете его обработать. Это меньше проблем для локального копирования, чем FTP.

Ответ 2

Это решение работало для меня:

File ff = new File(fileStr);

if(ff.exists()) {

    for(int timeout = 100; timeout>0; timeout--) {
        RandomAccessFile ran = null;

        try {
            ran = new RandomAccessFile(ff, "rw");
            break; // no errors, done waiting
        } catch (Exception ex) {
            System.out.println("timeout: " + timeout + ": " + ex.getMessage());
        } finally {
            if(ran != null) try {
                ran.close();
            } catch (IOException ex) {
                //do nothing
            }

            ran = null;
        }

        try {
            Thread.sleep(100); // wait a bit then try again
        } catch (InterruptedException ex) {
            //do nothing
        }
    }

    System.out.println("File lockable: " + fileStr +
                 (ff.exists()?" exists":" deleted during process"));
} else {
    System.out.println("File does not exist: " + fileStr);
}

Это решение зависит от того, что вы не можете открыть файл для записи, если другой процесс открыт. Он будет оставаться в цикле до тех пор, пока не будет достигнуто значение таймаута или файл не будет открыт. Значения таймаута должны быть скорректированы в зависимости от реальных потребностей приложения. Я также пробовал этот метод с каналами и tryLock(), но он не казался необходимым.

Ответ 3

Вы хотите сказать, что вы ждёте времени lastModified для урегулирования? В лучшем случае это будет бит-и-промах.

Как насчет того, чтобы открыть файл с возможностью записи (добавление, а не обрезание файла, конечно)? Это не удастся, если другой процесс все еще пытается записать на него. Это немного уродливо, особенно, поскольку это может быть случай использования исключений для управления потоком (ick), но я думаю, что это сработает.

Ответ 4

Если я правильно понял вопрос, вы ищете способ отличить, завершено ли или завершено копирование файла?

Как насчет сравнения размера исходного и целевого файлов (т.е. file.length())? Если они равны, то копирование завершено. В противном случае он все еще продолжается.

Я не уверен, что он эффективен, так как он все равно потребует опроса. Но это может "работать".

Ответ 5

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

http://www.missiondata.com/blog/java/28/file-upload-progress-with-ajax-and-java-and-prototype/

Загрузка файлов с помощью Java (с индикатором выполнения)

Ответ 6

Мы использовали для контроля изменения размера файла, чтобы определить, является ли файл неполным или нет.

мы использовали Spring интеграцию конечной точки файла для выполнения опроса для каталога за каждые 200 мс.

Как только файл обнаружен (независимо от того, завершен он или нет), у нас есть фильтр файлов клиента, который будет иметь метод интерфейса "accept (File file)", чтобы вернуть флаг, указывающий, можем ли мы обрабатывать файл,

Если False возвращается фильтром, этот экземпляр FILE будет проигнорирован, и он будет отображаться во время следующего опроса для того же процесса фильтрации.

Фильтр выполняет следующие действия:

Сначала мы получим его текущий размер файла. и мы будем ждать 200 мс (может быть меньше) и снова проверить размер. Если размер отличается, мы будем повторять попытку в 5 раз. Только когда размер файла перестанет расти, файл будет отмечен как COMPLETED (т.е. Вернет true).

Используемый пример кода:

public class InCompleteFileFilter<F> extends AbstractFileListFilter<F> {

    protected Object monitor = new Object();
    @Override
    protected boolean accept(F file) {
    synchronized (monitor){

        File currentFile = (File)file;

        if(!currentFile.getName().contains("Conv1")){return false;}

        long currentSize = currentFile.length();
        try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
        int retryCount = 0;
        while(retryCount++ < 4 && currentFile.length() > currentSize){
            try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
        }

        if(retryCount == 5){
            return false;
        }else{
            return true;
        }
    }
    }
}