java (1.6) 如何知道文件复制是否“正在进行”/完成
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/750471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to know whether a file copying is 'in progress'/complete in java (1.6)
提问by Krishna Kumar
I am writing a directory monitoring utility in java(1.6) using polling at certain intervals using lastModified
long value as the indication of change. I found that when my polling interval is small (seconds) and the copied file is big then the change event is fired before the actual completion of file copying.
我正在 java(1.6) 中编写目录监视实用程序,使用lastModified
长值作为更改指示以特定时间间隔轮询。我发现当我的轮询间隔很小(秒)并且复制的文件很大时,在实际完成文件复制之前会触发更改事件。
I would like to know whether there is a way I can find the status of file like in transit, complete etc.
我想知道是否有办法找到文件的状态,如传输中、完成等。
Environments: Java 1.6; expected to work on windows and linux.
环境:Java 1.6;预计适用于 windows 和 linux。
回答by Jon Skeet
Do you mean that you're waiting for the lastModified
time to settle? At best that will be a bit hit-and-miss.
你的意思是你在等待lastModified
时间安定下来?充其量这会有点碰运气。
How about trying to open the file with write access (appending rather than truncating the file, of course)? That won't succeed if another process is still trying to write to it. It's a bit ugly, particularly as it's likely to be a case of using exceptions for flow control (ick) but I think it'll work.
尝试以写访问权限打开文件(当然是附加而不是截断文件)如何?如果另一个进程仍在尝试写入它,那将不会成功。这有点难看,特别是因为它可能是使用异常进行流控制(ick)的情况,但我认为它会起作用。
回答by green_t
If I understood the question correctly, you're looking for a way to distinguish whether the copying of a file is complete or still in progress?
如果我正确理解了这个问题,您正在寻找一种方法来区分文件的复制是完成还是仍在进行中?
How about comparing the size of the source and destination file (i.e. file.length())? If they're equal, then copying is complete. Otherwise, it's still in progress.
如何比较源文件和目标文件的大小(即 file.length())?如果它们相等,则复制完成。否则,它仍在进行中。
I'm not sure it's efficient since it would still require polling. But it "might" work.
我不确定它是否有效,因为它仍然需要轮询。但它“可能”起作用。
回答by paxdiablo
There are two approaches I've used in the past which are platform agnostic.
我过去使用过两种与平台无关的方法。
1/ This was for FTP transfers where I controlled what was put, so it may not be directly relevant.
1/ 这是用于 FTP 传输的,我控制放置的内容,因此它可能没有直接关系。
Basically, whatever is putting a file file.txt
will, when it's finished, also put a small (probably zero-byte) dummy file called file.txt.marker
(for example).
基本上,无论放置什么文件file.txt
,当它完成时,也会放置一个名为file.txt.marker
(例如)的小(可能是零字节)虚拟文件。
That way, the monitoring tool just looks for the marker file to appear and, when it does, it knows the real file is complete. It can then process the real file and delete the marker.
这样,监控工具只查找出现的标记文件,当它出现时,它就知道真正的文件是完整的。然后它可以处理真实文件并删除标记。
2/ An unchanged duration.
2/ 持续时间不变。
Have your monitor program wait until the file is unchanged for N seconds (where N is reasonably guaranteed to be large enough that the file willbe finished).
让你的监控程序等待 N 秒,直到文件没有改变(其中 N 被合理地保证足够大,文件将被完成)。
For example, if the file size hasn't changed in 60 seconds, there's a good chance it's finished.
例如,如果文件大小在 60 秒内没有改变,则很有可能它已完成。
There's a balancing act between not thinking the file is finished just because there's no activity on it, and the wait once it is finished before you can start processing it. This is less of a problem for local copying than FTP.
在不认为文件完成只是因为文件上没有活动与等待完成后才能开始处理之间存在平衡。与 FTP 相比,这对于本地复制来说不是问题。
回答by miceuz
You could look into online file upload with progressbar techniques - they use OutputStreamListener and custom writer to notify the listener about bytes written.
您可以使用进度条技术查看在线文件上传 - 他们使用 OutputStreamListener 和自定义编写器来通知侦听器有关写入的字节数。
http://www.missiondata.com/blog/java/28/file-upload-progress-with-ajax-and-java-and-prototype/
http://www.missiondata.com/blog/java/28/file-upload-progress-with-ajax-and-java-and-prototype/
回答by Mr Ed
This solution worked for me:
这个解决方案对我有用:
File ff = new File(fileStr);
if(ff.exists()) {
for(int timeout = 100; timeout>0; timeout--) {
RandomAccessFile ran = null;
try {
ran = new RandomAccessFile(ff, "rw");
break; // no errors, done waiting
} catch (Exception ex) {
System.out.println("timeout: " + timeout + ": " + ex.getMessage());
} finally {
if(ran != null) try {
ran.close();
} catch (IOException ex) {
//do nothing
}
ran = null;
}
try {
Thread.sleep(100); // wait a bit then try again
} catch (InterruptedException ex) {
//do nothing
}
}
System.out.println("File lockable: " + fileStr +
(ff.exists()?" exists":" deleted during process"));
} else {
System.out.println("File does not exist: " + fileStr);
}
This solution relies on the fact that you can't open the file for writing if another process has it open. It will stay in the loop until the timeout value is reached or the file can be opened. The timeout values will need to be adjusted depending on the application's actual needs. I also tried this method with channels and tryLock(), but it didn't seem to be necessary.
此解决方案依赖于这样一个事实:如果另一个进程打开了该文件,则您无法打开该文件进行写入。它将停留在循环中,直到达到超时值或可以打开文件。超时值需要根据应用程序的实际需要进行调整。我也用channels和tryLock()尝试过这个方法,但似乎没有必要。
回答by Feng
We used to monitor the File Size change for determine whether the File is inComplete or not.
我们用来监控文件大小的变化,以确定文件是否不完整。
we used Spring integration File endpoint to do the polling for a directory for every 200 ms.
我们使用 Spring 集成文件端点每 200 毫秒对目录进行一次轮询。
Once the file is detected(regardless of whether it is complete or not), We have a customer File filter, which will have a interface method "accept(File file)" to return a flag indicating whether we can process the file.
一旦检测到文件(无论是否完整),我们就有了一个客户文件过滤器,它会有一个接口方法“accept(File file)”来返回一个标志,表明我们是否可以处理文件。
If the False is returned by the filter, this FILE instance will be ignored and it will be pick up during the next polling for the same filtering process..
如果过滤器返回 False,则此 FILE 实例将被忽略,并将在下一次轮询相同过滤过程时被拾取。
The filter does the following:
过滤器执行以下操作:
First, we get its current file size. and we will wait for 200ms(can be less) and check for the size again. If the size differs, we will retry for 5 times. Only when the file size stops growing, the File will be marked as COMPLETED.(i.e. return true).
首先,我们得到它当前的文件大小。我们将等待 200 毫秒(可以更短)并再次检查大小。如果大小不同,我们将重试 5 次。只有当文件大小停止增长时,文件才会被标记为已完成。(即返回真)。
Sample code used is as the following:
使用的示例代码如下:
public class InCompleteFileFilter<F> extends AbstractFileListFilter<F> {
protected Object monitor = new Object();
@Override
protected boolean accept(F file) {
synchronized (monitor){
File currentFile = (File)file;
if(!currentFile.getName().contains("Conv1")){return false;}
long currentSize = currentFile.length();
try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
int retryCount = 0;
while(retryCount++ < 4 && currentFile.length() > currentSize){
try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
}
if(retryCount == 5){
return false;
}else{
return true;
}
}
}
}