Java 7 WatchService - 进程无法访问该文件,因为它正在被另一个进程使用
我遵循Watching a Directory更改Java7 nio2教程,使用代码示例WatchDir.java递归监视目录的全部内容。Java 7 WatchService - 进程无法访问该文件,因为它正在被另一个进程使用
的代码看起来是这样的:
// Get list of events for the watch key.
for (WatchEvent<?> event : key.pollEvents()) {
// This key is registered only for ENTRY_CREATE events, but an OVERFLOW event
// can occur regardless if events are lost or discarded.
if (event.kind() == OVERFLOW) {
continue;
}
// Context for directory entry event is the file name of entry.
@SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path fileName = ev.context();
Path fullPath = dir.resolve(fileName);
try {
// Print out event.
System.out.print("Processing file: " + fileName);
processed = fileProcessor.processFile(fullPath);
System.out.println("Processed = " + processed);
if (processed) {
// Print out event.
System.out.println(" - Done!");
}
}
catch (FileNotFoundException e) {
System.err.println("Error message: " + e.getMessage());
}
catch (IOException e) {
System.err.println("Error processing file: " + fileName.toString());
System.err.println("Error message: " + e.getMessage());
}
好了,所以这个问题(其中我肯定做一些愚蠢的事)就在这里:
processed = fileProcessor.processFile(fullPath);
而且它的作用是这样的:
public synchronized boolean processFile(Path fullPath) throws IOException {
String line;
String[] tokens;
String fileName = fullPath.getFileName().toString();
String fullPathFileName = fullPath.toString();
// Create the file.
File sourceFile = new File(fullPath.toString());
// If the file does not exist, print out an error message and return.
if (sourceFile.exists() == false) {
System.err.println("ERROR: " + fullPathFileName + ": No such file");
return false;
}
// Check file extension.
if (!getFileExtension(fullPathFileName).equalsIgnoreCase("dat")) {
System.out.println(" - Ignored.");
return false;
}
// Process source file.
try (BufferedReader bReader = new BufferedReader(new FileReader(sourceFile))) {
int type;
// Process each line of the file.
while (bReader.ready()) {
// Get a single line.
line = bReader.readLine();
// Get line tokens.
tokens = line.split(delimiter);
// Get type.
type = Integer.parseInt(tokens[0]);
switch (type) {
// Type 1 = Salesman.
case 1:
-> Call static method to process tokes.
break;
// Type 2 = Customer.
case 2:
-> Call static method to process tokes.
break;
// Type 3 = Sales.
case 3:
-> Call static method to process tokes.
break;
// Other types are unknown!
default:
System.err.println("Unknown type: " + type);
break;
}
}
PrintStream ps = null;
try {
// Write output file.
// Doesn't matter.
}
finally {
if (ps != null) {
ps.close();
}
}
return true;
}
}
我第一次处理一个事件,它一切正常!即使有超过1个文件需要处理。但在连续的时间,我得到这个错误信息:
,因为它正由另一个进程使用该进程无法访问该文件
我在做什么错在这里?我能做些什么来处理成功的连续文件?我忘了提
两个重要注意事项:
- 我使用Windows 7
- 当我运行在调试模式下的应用程序,它的工作原理。
编辑:如果我添加一个睡觉前我尝试使用的文件,它的工作原理:
Thread.sleep(500);
// Process source file.
try (BufferedReader bReader = new BufferedReader(new FileReader(sourceFile))) {
那么,有没有可能是窗口未解锁的时间中的文件?我如何解决这个问题(以正确的方式)?
好的,我找到了一个解决方案。我不知道这是否是这样做的最好方法,但它是有效的。 不幸的是,即使文件仍然被Windows锁定,file.canRead()和file.canWrite()都返回true。所以我发现,如果我尝试用相同的名称“重命名”它,我知道Windows是否在使用它。所以这是我做的:
while(!sourceFile.renameTo(sourceFile)) {
// Cannot read from file, windows still working on it.
Thread.sleep(10);
}
我有类似的问题。但是我的文件在被复制时没有被锁定。如果我在创建活动后立即尝试阅读它,那是空的。
我认为你的情况没有必要的技巧,你可以简单地处理错误,如果你得到的错误比你可以执行睡眠,然后再试一次。但对我来说这不适合我。我没有得到错误。所以我尝试了你的解答,并且我明白这也是不能接受的,因为除了阅读,我没有权利。所以我可以推荐我的'技巧'。我使用的是类java.io.RandomAccessFile中:
List<String> lines = null;
while(true){
try(RandomAccessFile raf = new RandomAccessFile(fileFullPath.toFile() , "r")){
lines = Files.readAllLines(fileFullPath , Charset.forName(ENCODING));
break;
}catch(FileNotFoundException ex){
LOG.warn("File isn't yet completed: {}",ex.getMessage());
LOG.info("Waiting {} for next attempt to read it" , SLEEP_INTERVAL_READING);
try {
Thread.sleep(SLEEP_INTERVAL_READING);
} catch (InterruptedException e) {
LOG.error("Waiting was interrupted",e);
}
}catch(Exception ex){
LOG.error("Error in reading file ",ex);
clear();
return false;
}
}
当事件类型的ENTRY_MODIFY请允许当前线程睡眠几秒钟。我不知道为什么会发生这种情况,但有一次在我的日志中打印了多个ENTRY_MODIFY事件。取决于你的文件大小,请设置睡眠时间。
if(kind == StandardWatchEventKinds.ENTRY_MODIFY){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//toDo - something
}
它的工作:) – 2016-04-06 14:11:53
好戏!它帮助我了! – 2017-03-02 21:27:46