如何处理不完整的文件?获得例外

时间:2009-02-04 06:26:34

标签: java multithreading file-io ftp

我需要创建一个java程序,它将创建线程来搜索特定文件夹(源文件夹)中的文件,并在源文件中找到文件后立即选择文件进行处理工作(将其转换为csv文件格式)夹。我现在面临的问题是来源文件夹的文件是大尺寸(FTP工具用于将文件从服务器复制到源文件夹),线程在完全复制到源文件夹并抛出异常之前立即挑选该文件。如何在文件完全复制到源文件夹之前停止线程?只有在将文件完全复制到源文件夹后,才必须选择要处理的文件。

7 个答案:

答案 0 :(得分:4)

最安全的方法是将文件下载到其他位置,然后将其移动到目标文件夹。

Bombe提到的另一个变体是在下载后将文件名更改为其他扩展名,并仅查找具有该扩展名的文件。

答案 1 :(得分:4)

我只读取未处于写入模式的文件。这是最安全的,因为这意味着没有其他进程在此文件中写入。您可以使用File类的canWrite方法检查文件是否处于写入模式。

这个解决方案对我来说很好,因为我也有完全相同的情况。

答案 2 :(得分:3)

你可以尝试不同的东西:

  • 反复检查最后修改日期和文件大小,直到它在给定时间内不再变化,然后处理它。(正如qbeuek指出的那样,这既不安全也不确定。)
  • 仅处理名称与特定条件匹配的文件(例如* .dat)。将FTP上传/下载过程更改为使用其他名称(例如* .dat.temp)上载/下载文件,并在文件完成后重命名。
  • 将文件下载到其他位置,并在文件完成后将其移至处理目录。
  • 正如Vinegar所说,如果它第一次不起作用,请稍后再试。 :)

答案 3 :(得分:2)

如果您对执行FTP的进程有一些控制权,您可能会在大文件的ftp完成后立即在源目录中创建“标记文件”。

然后你的Java线程必须检查这个标志文件的存在,如果它存在,那么就有一个文件可以在源目录中处理。在处理大文件之前,线程应该删除标志文件。

标记文件可以是任何内容(甚至是空文件)。

答案 4 :(得分:1)

假设您无法控制FTP进程......

让它像这样。当您收到异常时,请尝试下次再次处理。重复它直到文件得到处理。如果在异常的情况下保留一些属性以便稍后检查它是很好的,例如;名称,最后修改,大小。

在决定稍后处理之前检查确切的异常,可能由于其他原因而发生异常。

答案 5 :(得分:0)

如果你的操作系统是Linux,你的内核> 2.6.13,您可以使用名为inotify的文件系统事件通知API。 这里有一个Java实现:https://bitbucket.org/nbargnesi/inotify-java

以下是一个示例代码(深受网站启发)。

        try {
        Inotify i = new Inotify();
        InotifyEventListener e = new InotifyEventListener() {

            @Override
            public void filesystemEventOccurred(InotifyEvent e) {
                System.out.println("inotify event occurred!");
            }

            @Override
            public void queueFull(EventQueueFull e) {
                System.out.println("inotify event queue: " + e.getSource() +
                        " is full!");
            }

        };
        i.addInotifyEventListener(e);
        i.addWatch(System.getProperty("user.home"), Constants.IN_CLOSE_WRITE);
    } catch (UnsatisfiedLinkError e) {
        System.err.println("unsatisfied link error");
    } catch (UserLimitException e) {
        System.err.println("user limit exception");
    } catch (SystemLimitException e) {
        System.err.println("system limit exception");
    } catch (InsufficientKernelMemoryException e) {
        System.err.println("insufficient kernel memory exception");
    }

答案 6 :(得分:0)

这是在Grails中,我正在使用来自Apache commons成名的FileUtils库。 sizeof函数返回以字节为单位的大小。

    def fileModified = sourceFile.lastModified()
    def fileSize = FileUtils.sizeOf(sourceFile)

    Thread.sleep(3000) //sleep to calculate size difference if the file is currently getting copied

    if((fileSize != FileUtils.sizeOf(sourceFile)) && (fileModified != sourceFile.lastModified())) //the file is still getting copied to return 
    {
        if(log.infoEnabled)
            log.info("File is getting copied!")
        return
    } 

    Thread.sleep(1000) //breather for picking up file just copied. 

请注意,这还取决于您用于传输文件的实用程序或操作系统。 最安全的做法是复制已复制或已复制到不同文件或目录的文件。复制过程非常强大,它可以确保在复制过程之后文件存在。我使用的是来自commons API。

FileUtils.copyFileToDirectory(文件f,目录D)

如果您要复制正在复制的大文件,请注意这需要时间,您可能希望以并行线程开始此操作,或者最好有一个专门用于传输过程的单独应用程序。