Java File.exists和其他文件操作返回错误的现有文件结果(网络、macosx)
文件系统airporthd从一开始就被挂载(AFP),当我启动这个小程序时,文件就存在了。 我一整天都在试图弄明白为什么下面的方法不起作用,但找不到任何解决办法:Java File.exists和其他文件操作返回错误的现有文件结果(网络、macosx),java,macos,networking,filesystems,Java,Macos,Networking,Filesystems,文件系统airporthd从一开始就被挂载(AFP),当我启动这个小程序时,文件就存在了。 我一整天都在试图弄明白为什么下面的方法不起作用,但找不到任何解决办法: public static void main(String[] arguments) { while(1==1) { File f=new File( "/Volumes/AirportHDD/test/lock.csv"); System.out.pr
public static void main(String[] arguments)
{
while(1==1)
{
File f=new File(
"/Volumes/AirportHDD/test/lock.csv");
System.out.println(f.exists());
AmySystem.sleep(100);
}
}
输出为:
真的,真的
一旦我从另一台计算机上删除该文件(AirportHDD是通过网络挂载的硬盘),则输出会一直显示:
真的,真的。。。
当我打开finder并转到这个目录时,输出变为:false,false
再次添加文件(通过另一台pc)时,输出仍为:
假,假
但如果您再次打开finder并单击目录,finder显示现有文件,则输出会突然更改为:false、true、true、true、
注:
- 此外,只要java“认为”文件不存在,所有其他文件操作(如打开以便读取)都会失败
- 如果程序本身正在创建和删除文件,则问题不会发生
- 在测试samba时发现,共享一切都没问题,但使用AFP就行不通了
有没有一种方法可以告诉java做与finder相同的事情,比如刷新,或者不要尝试缓存,不管怎样?我想您可能正在寻找。甲骨文公司也很友好地提供了一个解决方案 因为不能保证这些链接的寿命,我将在几分钟内编辑一个示例代码。我只是想让你知道,我想我找到了一些东西,以防你想自己去看 更新 在链接教程之后,我产生了如下代码。我不确定它是否有效(没有时间测试),但它可能足以让您开始。
WatchService
还有一个take()
方法,该方法将等待事件,这意味着您可能会根据上次提供的输出假设文件存在(或不存在)。这将真正取决于这个程序将与什么交互
如果这有效,那就好了。如果没有,也许我们可以根据您遇到的任何错误来解决它。或者,如果其他人比我更熟悉这一点,他们可能会提供更好的代码版本(或者更好的选择)
public static void main(String[] arguments) {
Path path = Paths.get("/Volumes/AirportHDD/test/lock.csv");
WatchService watcher = FileSystems.getDefault().newWatchService();
WatchKey key = null;
try {
key = path.register(watcher,
ENTRY_CREATE,
ENTRY_DELETE);
} catch (IOException x) {
System.err.println(x);
}
while(true) {//I tend to favor this infinite loop, but that's just preference.
key = watcher.poll();
if(key != null) {
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == OVERFLOW || kind == ENTRY_DELETE) {
System.out.println(false);
}
else if (kind == ENTRY_CREATE) {
System.out.println(true);
}
}//for(all events)
}//if(file event occured)
else {
File f=new File(path);
System.out.println(f.exists());
}//else(no file event occured)
AmySystem.sleep(100);
}//while(true)
}//main() method
publicstaticvoidmain(字符串[]参数){
Path Path=Path.get(“/Volumes/airporthd/test/lock.csv”);
WatchService watcher=FileSystems.getDefault().newWatchService();
WatchKey=null;
试一试{
key=路径寄存器(watcher,
创建的入口,
条目(删除);
}捕获(IOX异常){
系统错误println(x);
}
虽然(真的){//我倾向于这个无限循环,但这只是偏好。
key=watcher.poll();
if(key!=null){
for(WatchEvent事件:key.pollEvents()){
WatchEvent.Kind-Kind=event.Kind();
if(种类==溢出| |种类==条目_删除){
System.out.println(假);
}
else if(种类==条目\u创建){
System.out.println(真);
}
}//(所有事件)
}//如果(发生文件事件)
否则{
文件f=新文件(路径);
System.out.println(f.exists());
}//else(未发生文件事件)
睡眠系统(100);
}//while(true)
}//main()方法
问题在于网络文件系统AFP。通过使用SAMBA,一切都像预期的那样工作
在这些情况下,使用AFP时,操作系统可能会在OSX中返回错误的文件信息。下面是一个JUnit测试,显示了问题所在 在OSX小牛上使用Samba仍然会出现问题。可能的原因 由以下语句解释: 它积极缓存文件和文件夹属性,并使用机会锁定来更好地缓存数据。 请在下面找到一个检查文件,它将实际尝试读取几个字节并强制进行真正的文件访问,以避免缓存错误行为 JUnit测试:
/**
* test file exists function on Network drive
* @throws Exception
*/
@Test
public void testFileExistsOnNetworkDrive() throws Exception {
String testFileName="/Volumes/bitplan/tmp/testFileExists.txt";
File testFile=new File(testFileName);
testFile.delete();
for (int i=0;i<10;i++) {
Thread.sleep(50);
System.out.println(""+i+":"+OCRJob.checkExists(testFile));
switch (i) {
case 3:
// FileUtils.writeStringToFile(testFile, "here we go");
Runtime.getRuntime().exec("/usr/bin/ssh phobos /usr/bin/touch "+testFileName);
break;
}
}
}
/**
* check if the given file exists
* @param f
* @return true if file exists
*/
public static boolean checkExists(File f) {
try {
byte[] buffer = new byte[4];
InputStream is = new FileInputStream(f);
if (is.read(buffer) != buffer.length) {
// do something
}
is.close();
return true;
} catch (java.io.IOException fnfe) {
}
return false;
}
我猜当你通过finder打开它时,它会被装入
。可用和安装是不同的。@rocketboy:这与报告的症状不匹配。显然,如果报告文件存在(初始true
true
true
),则文件系统已装入。文件系统从一开始就装入,更正了启动情况这是什么类型的网络装入?这听起来确实像是一个缓存问题,在NFS上很常见。它的AFP,是的,它表明只有finder可以执行刷新之类的操作,而其他操作系统调用仍然会得到错误的结果。听起来不错,但我喜欢使用静态方法来告诉我文件是否存在。如果我得到了这项手表服务,我需要注册更改,这些更改可能难以在当前设计中实现。我不会假装了解您的设计,但我知道有些解决方案不兼容。我不确定这是否适用于您的系统设计,但我想这将是您的决定。如果结果证明它不起作用,我相信其他人会找到一个不同的解决方案。thx很多时候我都会尝试实现它,我只是在测试samba共享时发现,一切都可以,但对于AFP,对于当前在OS Mavericks上的samba实现,上面的解决方案无法工作