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

1

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

public class LiveDetectionsProvider extends DetectionsProvider {
protected LiveDetectionsProvider.MonitorDirectory monitorDirectory = null;
protected TimeModel timeModel = null;
private ArrayList<String> loaded = new ArrayList();
private File topLayerFolder = null;
public LiveDetectionsProvider(String directory, String id) {
    super(directory, id);
    timeModel = super.timeModel;
}
/**
 * Initialize the data provider.
 */
public void initialize() {
    try {
        topLayerFolder = new File(directory);
        File[] dir = topLayerFolder.listFiles();
        for (File file : dir) {
            loaded.add(file.getName());
        }
        monitorDirectory = new MonitorDirectory();
        monitorDirectory.execute();
    }
    catch (Exception ex) {
        Logger.getLogger(LiveDetectionsProvider.class.getName()).log(Level.SEVERE, "Failed to read detection\n{0}", ex.getMessage());
    }
    super.initialize();
}
/**
 * Un-initialize the data provider.
 */
public void uninitialize() {
    super.uninitialize();
    if (monitorDirectory != null) {
        monitorDirectory.continuing = false;
    }
}
/**
 * The class that is used to load the detection points in a background
 * thread.
 */
protected class MonitorDirectory extends SwingWorker<Void, Void> {
    public boolean continuing = true;
    /**
     * The executor service thread pool.
     */
    private ExecutorService executor = null;
    /**
     * The completion service that reports the completed threads.
     */
    private CompletionService<Object> completionService = null;
    @Override
    protected Void doInBackground() throws Exception {
        int count = 0;
        executor = Executors.newFixedThreadPool(1);
        completionService = new ExecutorCompletionService<>(executor);
        while (continuing && topLayerFolder != null) {
            File[] dir = topLayerFolder.listFiles();
            Thread.sleep(10);
            ArrayList<File> filesToLoad = new ArrayList();
            for (File file : dir) {
                if (!loaded.contains(file.getName())) {
                    long filesize = 0;
                    boolean cont = true;
                    while (cont) {
                        if (file.length() == filesize) {
                            cont = false;
                            Thread.sleep(3);
                            filesToLoad.add(file);
                        }
                        else {
                            filesize = file.length();
                            Thread.sleep(3);
                        }
                    }
                    Thread.sleep(3);
                }
            }
            for (File file : filesToLoad) {
                timeModel.setLoadingData(LiveDetectionsProvider.this.hashCode(), true);
                completionService.submit(Executors.callable(new ReadDetection(file, false)));
                while (completionService.take() == null) {
                    Thread.sleep(2);
                }
                loaded.add(file.getName());
                count++;
                Logger.getLogger(LiveDetectionsProvider.class.getName()).log(Level.SEVERE, "Detection Message Count:" + count);
            }
            detectionsModel.fireStateChanged(DetectionsModel.CHANGE_EVENT_DETECTIONS);
            timeModel.setLoadingData(LiveDetectionsProvider.this.hashCode(), false);
        }
        return null;
    }
}
}

Файл обрабатывается в строке с помощью

completionService.submit(Executors.callable(new ReadDetection(file, false)));

Файл на этом этапе еще не закончил писать и, таким образом, не работает. Я пробовал спящий мой поток, чтобы замедлить его, и я попытался проверить размер файла, который не изменился. Мой тестовый пример: я разархивирую tar файл, содержащий тысячи файлов размером 1000 КБ.

  • 0
    Пожалуйста, не забудьте добавить '?' на вопросы! Некоторые люди делают поиск на странице для «?» и если ничего не существует в «вопросе», переходите непосредственно к следующему (фактическому) вопросу в строке.
  • 0
    Есть ли способ изменить заголовок, чтобы добавить? к этому?
Показать ещё 1 комментарий
Теги:

3 ответа

-1
Лучший ответ

Сначала да, компилирует, посмотри решение, которое я разместил по отношению к коду. В моем вопросе. Вы заменяете

For(File file: dir){
while(!file.renameTo(file)){
Thread.sleep(1)
}
// In my code I check to see if the file name is already in the list which 
// contains files that have been previously loaded if its not I add it to a list
// of files to be processed
}

in для

        for (File file : dir) {
            if (!loaded.contains(file.getName())) {
                long filesize = 0;
                boolean cont = true;
                while (cont) {
                    if (file.length() == filesize) {
                        cont = false;
                        Thread.sleep(3);
                        filesToLoad.add(file);
                    }
                    else {
                        filesize = file.length();
                        Thread.sleep(3);
                    }
                }
                Thread.sleep(3);
            }
        }

Извините, я забыл поставить теги комментариев//в строке, в которой говорилось, делать то, что вам нужно делать здесь.

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

  • 0
    (Я не голосовал.) У меня не работает, Windows 10, Java 1.8.0_144. У меня есть одна JVM для создания и записи в файлы. Другой пытается определить, когда файлы могут быть перемещены с помощью Files.move (). Я продолжаю получать перемещенные файлы размером 0, которые затем все еще записываются, как будто местоположение не имеет значения вообще. В любом случае, я просто добавил ваш file.renameTo (файл) непосредственно перед моей командой перемещения, и, если он вернет false, я немедленно отправлю System.exit (). Но программа никогда не выходит в этом месте.
3

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

  • 0
    На самом деле это не так просто, как звучит в Windows. Мое решение, реализованное в том же духе, работает в 99,5% случаев (более подробную информацию см. В stackoverflow.com/questions/29923008/… )
0

Используйте "файл флага": после завершения файла file.txt укажите это, создав файл .flg - процесс потребления должен ждать появления .flg.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню