在 Java 中区分 ESTALE 和 ENOENT 的最佳方法
Posted
技术标签:
【中文标题】在 Java 中区分 ESTALE 和 ENOENT 的最佳方法【英文标题】:Best way to differentiate between ESTALE and ENOENT in Java 【发布时间】:2013-05-30 10:54:16 【问题描述】:我正在尝试编写一个在 NFS 文件系统上的 Linux 环境中运行的 Java 应用程序。
我注意到,当我调用java.io.File.exists()
时,它对ESTALE
(陈旧的NFS 文件句柄)和ENOENT
(没有这样的文件或目录)都返回false。对于我的应用程序,我需要能够区分两者。
目前我正在考虑使用 JNA 实现 stat()
调用,但这似乎有点过头了,因为必须实现整个 stat 结构和所有看起来如此依赖于平台的 __xstat64
东西。
有没有一种简单的方法可以在像File.exists()
这样的Java 调用之后简单地获取底层errno
或任何其他解决此问题的想法?
【问题讨论】:
【参考方案1】:使用 JNA,您实际上不必实现 stat
结构;您只需为其分配足够大的内存以表示本机结构。
然后您可以调用Native.getLastError()
来检索errno
值。
Pointer fake_stat = new Memory(2048); // big enough
if (clib.stat(filename, fake_stat) != 0)
int errno = Native.getLastError();
...
【讨论】:
我喜欢这个建议。我还考虑过实现access(file, F_OK)
,这要简单得多,但结果也没有区分ESTALE
和ENOENT
。然而,最终我们找到了一个不需要这种区分的解决方案。【参考方案2】:
如果您的性能要求很低,我将只实现一个小型 C 程序,它为给定的文件名调用 stat
并将 errno
的值打印到标准输出。然后从 Java 中调用它:
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char * argv[])
struct stat buf;
char const * const fileName = argv[1];
int const ret = stat(fileName, &buf);
printf("File %s: Return %d, errno %d\n", fileName, ret, errno);
if (errno)
perror("Error");
从命令行,这需要 4ms。在您的情况下,如果以前的 exists()
返回 false,您可能只需要调用它。
其他可能性:考虑将它包装在一个小型 TCP 服务器中,并让 Java 使用套接字与其通信。或者将其作为apache中的CGI脚本,让Java使用HTTP。
如果这仍然太慢,你可能不得不走 JNI/JNA 的方式。
【讨论】:
以上是关于在 Java 中区分 ESTALE 和 ENOENT 的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
是否有一个 Eclipse 插件可以让您在多个 Subversion 修订中区分单个 Java 方法?
Eclipse 或 Notepad++ 中区分大小写的字符串替换