Java 如何处理不完整的文件?破例

Java 如何处理不完整的文件?破例,java,multithreading,file-io,ftp,Java,Multithreading,File Io,Ftp,我需要创建一个java程序,它将创建线程来搜索特定文件夹(源文件夹)中的文件,并在找到源文件夹中的文件后立即选择该文件进行处理(将其转换为csv文件格式)。我现在面临的问题是,到源文件夹的文件太大(FTP工具用于将文件从服务器复制到源文件夹),线程会在文件完全复制到源文件夹之前立即拾取该文件并引发异常。如何停止线程,直到文件完全复制到源文件夹?。只有在文件完全复制到源文件夹后,它才能选择要处理的文件。假设您无法控制FTP进程 就这样吧。当您得到异常时,请尝试下次再次处理它。重复此操作,直到文件得

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

假设您无法控制FTP进程

就这样吧。当您得到异常时,请尝试下次再次处理它。重复此操作,直到文件得到处理。保留一些属性以防出现异常,以便以后检查,这很好,比如;名称、上次修改、大小


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

如果您对执行FTP的过程有一定的控制权,则可能会让它在完成大文件的FTP后立即在源目录中创建一个“标志文件”

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


标志文件可以是任何文件(甚至是空文件)。

您可以尝试不同的方法:

  • 反复检查上次修改日期和文件大小,直到在给定的时间内文件不再更改,然后处理它。(正如qbeuek所指出的,这既不安全也不确定。)
  • 仅处理名称符合某些条件(例如.*.dat)的文件。将FTP上载/下载过程更改为上载/下载具有不同名称的文件(例如.*.dat.temp),并在文件完成后重命名这些文件
  • 将文件下载到其他位置,完成后将其移动到处理目录
  • 正如醋所说,如果第一次不起作用,请稍后再试。:)
最安全的方法是将文件下载到其他位置,然后将其移动到目标文件夹


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

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


这个解决方案对我来说很好,因为我也有与您面临的完全相同的场景。

如果您的操作系统是Linux,并且您的内核>2.6.13,那么您可以使用名为的文件系统事件通知API。 这里有一个Java实现:

下面是一个示例代码(灵感来源于网站)


这是在Grails中,我使用的是apachecommons中的
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的

copyFileToDirectory(文件f,目录D)


如果您正在复制一个正在被复制的巨大文件,请注意这将需要时间,您可能希望以并行线程方式启动它,或者最好有一个专用于传输过程的单独应用程序

很高兴知道,有什么例外?我不知道为什么我们有时会投反对票。人们开始到处射击。声誉太低,不能投某人的票。它必须更高,可能是1000或2000。好吧,有时候我投东西只是为了平衡反对票,给votee+8分,否则他们不会得到,所以这是一些东西。在这种情况下,我会投票赞成你的答案,很难。我投票反对你,因为你的建议列表上的第一项既不安全也不确定。我从来没有声称它是安全的,但你是对的。它可能不应该在清单上。你能详细说明一下“一旦它们完成”部分吗。。。您如何判断文件何时已完全传输到另一个文件夹中?或者在复制/重命名过程中是否会失败?+1这不是最安全的方法,而是唯一的方法。所有其他选项要么浪费资源,要么不安全:)
    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.