在 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),这要简单得多,但结果也没有区分ESTALEENOENT。然而,最终我们找到了一个不需要这种区分的解决方案。【参考方案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 的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

java中区分大小写吗???

perl 脚本来搜索 java 源代码中区分大小写的文件名

是否有一个 Eclipse 插件可以让您在多个 Subversion 修订中区分单个 Java 方法?

Eclipse 或 Notepad++ 中区分大小写的字符串替换

在firebase中区分普通用户和管理员的最佳方法是啥? [复制]

Spark 中区分大小写的连接