我需要创建一个java程序,它将创建线程来搜索特定文件夹(源文件夹)中的文件,并在源文件中找到文件后立即选择文件进行处理工作(将其转换为csv文件格式)夹。我现在面临的问题是来源文件夹的文件是大尺寸(FTP工具用于将文件从服务器复制到源文件夹),线程在完全复制到源文件夹并抛出异常之前立即挑选该文件。如何在文件完全复制到源文件夹之前停止线程?只有在将文件完全复制到源文件夹后,才必须选择要处理的文件。
答案 0 :(得分:4)
最安全的方法是将文件下载到其他位置,然后将其移动到目标文件夹。
Bombe提到的另一个变体是在下载后将文件名更改为其他扩展名,并仅查找具有该扩展名的文件。
答案 1 :(得分:4)
我只读取未处于写入模式的文件。这是最安全的,因为这意味着没有其他进程在此文件中写入。您可以使用File类的canWrite方法检查文件是否处于写入模式。
这个解决方案对我来说很好,因为我也有完全相同的情况。
答案 2 :(得分:3)
你可以尝试不同的东西:
答案 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)
如果您要复制正在复制的大文件,请注意这需要时间,您可能希望以并行线程开始此操作,或者最好有一个专门用于传输过程的单独应用程序。