在尝试处理文件之前如何验证文件是否已完成?

时间:2013-12-13 16:02:27

标签: java windows

很难对我的问题给出一个好的标题,但它如下。首先,我在Windows上执行此操作,它可能也可以在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)));

此时的文件仍未完成写入,因此失败。我试过睡觉我的线程慢下来,我已经尝试验证文件大小没有改变。我的测试用例是我解压缩包含大量1,000 KB文件的tar文件。

3 个答案:

答案 0 :(得分:3)

通常我通过在写入文件时创建临时文件来解决此问题。完成后,我重命名文件,只有重命名的文件可以处理。

答案 1 :(得分:0)

使用“标记文件”:一旦file.txt“完成”,通过创建文件来指示这一点。消费过程应该等待.flg出现。

答案 2 :(得分:-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

        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循环后的所有内容。我很好奇为什么我的芒果被视为子标题删除和锁定。此解决方案确实有效并解决了我的问题,并且任何有同样问题的人都会尝试处理仍在编写或复制到受监控目录的文件中的文件。