【问题标题】:Java 1.4.2 File.listFiles not working properly with CIFS mounts - workaround?Java 1.4.2 File.listFiles 不能与 CIFS 挂载一起正常工作 - 解决方法?
【发布时间】:2012-06-09 13:01:56
【问题描述】:

我正在使用 Java 1.4.2 和 Debian 6.0.3。网络中有一个共享的 Windows 文件夹,它使用 CIFS 通过 fstab 正确安装到 /mnt/share/(例如,它在操作系统中完全可见并允许所有操作)。但是,当我尝试在 Java 中执行此操作时:

System.out.println(new File("/mnt/share/").listFiles().length)

它总是返回0,这意味着listFiles返回的File[]是空的。同样的问题适用于/mnt/share/ 的每个子目录。 list 也返回空数组。有趣的是,其他File 函数,如“create”、“isDirectory”甚至“delete”都可以正常工作。从 USB 闪存驱动器 (fat32) 安装的目录也可以正常工作。

我在来自不同 Windows 系统的 2 个不同“共享文件夹”上对此进行了测试;一种使用基于域的身份验证系统,另一种使用“简单共享”——即访客访问。这种情况看起来很奇怪,因为挂载的目录应该成为文件系统的一部分,所以任何程序都可以使用它。至少我是这么认为的。

我想在我的程序中删除一个目录,我目前看不到其他方法,除了在listFiles 上递归行走,所以这个错误变得相当烦人。我能想到的唯一“解决方法”是以某种方式运行外部 bash 脚本,但这似乎是一个糟糕的解决方案。

编辑:这似乎是 1.4.2 特有的错误,在 Java 6 中一切正常。但我无法迁移,所以问题仍然存在。

您能建议一些解决方法吗?最好不要切换到第三方库而不是原生库,我不能说我喜欢为了单个代码行而重写整个项目的想法。

【问题讨论】:

  • 您为什么使用 Java 1.4.2?也许您可以尝试使用 Java 7 看看是否能解决问题?
  • 因为我的应用程序将在服务器上使用许多其他应用程序,这些应用程序已经运行了很长时间,我公司的高层因为潜在的向后兼容性而害怕迁移问题。不过,尝试使用较新的版本并没有什么坏处。我想是时候在家安装 Debian 了。不过,在我使用它时,如果有任何建议,我将不胜感激。
  • 你可以在同一台机器上使用多个版本的java。
  • 我知道的很多(实际上我确实安装了 1.6.0 和 1.4.2),只是我没有用另一个版本测试它的想法,但我走了现在下班,提前3天休息。今天问这个问题可能不是最好的主意,但无论如何。

标签: java linux cifs


【解决方案1】:

由于Java 1.2 有方法File.getCanonicalFile()。在您的安装目录的情况下,您应该以这种风格使用这个目录:

new File("/mnt/share/").getCanonicalFile().listFiles()

【讨论】:

  • 唉,不。这是我尝试的第一件事,并且产生了相同的结果。
【解决方案2】:

所以,在放弃两年半后,我遇到了同样的问题,再次卡住了 1.4.2,因为我需要将代码嵌入到过时的 Oracle Forms 10g 版本中。

如果有人偶然发现这个问题并决定正确解决它,而不是破解他的方式,它很可能与 CIFS 在安装远程文件系统时所做的(高度)异常 inode 映射有关,导致更多一些模糊的错误,其中一些可以在 serverfault 上找到。这种映射的副作用之一是所有目录的硬链接计数为零。另一个是所有目录的“大小”正好为 0,而不是通常的“扇区大小或更大”,即使使用ls 也可以检查。

如果不检查(专有)源代码,我无法确定,但我可以猜测 1.5 之前的 Java 使用了一些快捷方式,比如在内部检查链接计数,而不是用 C 实际调用 readdir(),这同样适用于任何挂载的FS。

无论如何,第二个副作用可用于创建一个简单的 File 包装器,它不会依赖系统调用,除非它怀疑目录是使用 CIFS 挂载的。 java.io.File 中的其他版本的listlistFiles 函数,即使是使用过滤器的函数,在内部都依赖于list(),所以只覆盖它是可以的。

我不关心listFiles 返回File[] 而不是FileEx[] 所以我没有费心去覆盖它,但它应该足够简单。显然,该代码只能在具有 ls 命令方便的类 Unix 系统中工作。

package FSTest;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

import java.util.ArrayList;

public class FileEx extends File
{
    public FileEx(String path)
    {
        super(path);
    }

    public FileEx(File f)
    {
        super(f.getAbsolutePath());
    }

    public String[] list()
    {
        if (this.canRead() && this.isDirectory())
            {
            /*
             * Checking the length of dir is not the most reliable way to distinguish CIFS mounts.
             * However, zero directory length generally indicates something unusual,
             * so calling ls on it wouldn't hurt. Ordinary directories don't suffer any overhead this way.
             * If this "zero-size" behavior is ever changed by CIFS but list() still won't work,
             * it will be safer to call super.list() first and call this.listUsingExec if returned array has 0 elements.
             * Though it might have serious performance implications, of course.
             */
            if (this.length() > 0)
                return super.list();
            else
                return this.listUsingExec();
           }
        else
            return null;
    }

    private String[] listUsingExec()
    {
        Process p;
        String command = "/bin/ls -1a " + this.getAbsolutePath();
        ArrayList list = new ArrayList();
        try
            {
            p = Runtime.getRuntime().exec(command);
            p.waitFor();
            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
            for (String line = reader.readLine(); line != null; line = reader.readLine())
                {
                if (!line.equalsIgnoreCase(".") && !line.equalsIgnoreCase(".."))
                    list.add(line);
               }
            String[] ret = new String[list.size()];
            list.toArray(ret);
            return ret;
           }
        catch (IOException e)
            {
            return null;
           }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-10
    • 2014-07-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多