15

我想检查现有文件是否位于特定目录或该目录的子目录中。

我有两个 File 对象。

File dir;
File file;

两者都保证存在。让我们假设

dir  = /tmp/dir 
file = /tmp/dir/subdir1/subdir2/file.txt

我希望此检查返回 true

现在我正在这样做检查:

String canonicalDir = dir.getCanonicalPath() + File.separator;
boolean subdir = file.getCanonicalPath().startsWith(canonicalDir);

这似乎适用于我有限的测试,但我不确定这是否会在某些操作系统上造成问题。我也不喜欢 getCanonicalPath() 会抛出我必须处理的 IOException。

有没有更好的办法?可能在某个图书馆?

谢谢

4

9 回答 9

14

除了来自 Rocketboy 的 asnwer 之外,使用getCanonicalPath()instad 的getAbsolutePath()so\dir\dir2\..\file转换为\dir\file

    boolean areRelated = file.getCanonicalPath().contains(dir.getCanonicalPath() + File.separator);
    System.out.println(areRelated);

或者

boolean areRelated = child.getCanonicalPath().startsWith(parent.getCanonicalPath() + File.separator);

不要忘记Exceptiontry {...} catch {...}.

注意:您可以使用FileSystem.getSeparator()而不是File.separator. 这样做的“正确”方法getCanonicalPath()是将要检查的目录作为 a String,然后检查是否以 a 结尾,File.separator如果不是,则添加File.separator到 that 的末尾String,以避免双斜杠。这样,如果 Java 决定返回带有斜线的目录,或者您的目录字符串来自Java.io.File.

注意2:感谢@david 指出File.separator问题。

于 2014-04-12T12:21:25.843 回答
9

我会创建一个小的实用程序方法:

public static boolean isInSubDirectory(File dir, File file) {

    if (file == null)
        return false;

    if (file.equals(dir))
        return true;

    return isInSubDirectory(dir, file.getParentFile());
}
于 2013-08-14T09:31:41.743 回答
8

这种方法看起来很可靠:

/**
 * Checks, whether the child directory is a subdirectory of the base 
 * directory.
 *
 * @param base the base directory.
 * @param child the suspected child directory.
 * @return true, if the child is a subdirectory of the base directory.
 * @throws IOException if an IOError occured during the test.
 */
public boolean isSubDirectory(File base, File child)
    throws IOException {
    base = base.getCanonicalFile();
    child = child.getCanonicalFile();

    File parentFile = child;
    while (parentFile != null) {
        if (base.equals(parentFile)) {
            return true;
        }
        parentFile = parentFile.getParentFile();
    }
    return false;
}

资源

它类似于 dacwe 的解决方案,但不使用递归(尽管在这种情况下应该不会有很大的不同)。

于 2014-07-30T11:56:14.343 回答
1

如果您打算使用文件和文件名,请检查 apache fileutils 和 filenameutils 库。充满了有用的(如果便携性是强制性的,还有门户)功能

于 2013-08-14T09:29:20.417 回答
0

您可以从特定 DIR 开始遍历文件树。在 Java 7 中,有Files.walkFileTree方法。您只需编写自己的访问者来检查当前节点是否是搜索文件。更多文档: http ://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#walkFileTree%28java.nio.file.Path,%20java.util.Set,%20int ,%20java.nio.file.FileVisitor%29

于 2013-08-14T09:38:21.787 回答
0
public class Test {
public static void main(String[] args) {
    File root = new File("c:\\test");
    String fileName = "a.txt";
    try {
        boolean recursive = true;

        Collection files = FileUtils.listFiles(root, null, recursive);

        for (Iterator iterator = files.iterator(); iterator.hasNext();) {
            File file = (File) iterator.next();
            if (file.getName().equals(fileName))
                System.out.println(file.getAbsolutePath());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

于 2013-08-14T09:29:36.237 回答
0

从 Java 7+ 开始,您可以这样做:

file.toPath().startsWith(dir.toPath());
于 2022-02-07T12:08:08.930 回答
0

您可以这样做,但它不会捕获每个用例,例如 dir = /somedir/../tmp/dir/etc...,除非文件也是这样定义的。

import java.nio.file.Path;
import java.nio.file.Paths;

public class FileTest {
    public static void main(final String... args) {
        final Path dir = Paths.get("/tmp/dir").toAbsolutePath();
        final Path file = Paths.get("/tmp/dir/subdir1/subdir2/file.txt").toAbsolutePath();
        System.out.println("Dir: " + dir);
        System.out.println("File: " + file);
        final boolean valid = file.startsWith(dir);
        System.out.println("Valid: " + valid);
    }
}

为了使检查正常工作,您确实需要使用toRealPath()or 在您的示例中映射这些getCanonicalPath(),但是您必须处理这些示例的异常,这是绝对正确的,您应该这样做。

于 2019-05-23T22:05:57.883 回答
-1

How about comparing the paths?

    boolean areRelated = file.getAbsolutePath().contains(dir.getAbsolutePath());
    System.out.println(areRelated);

or

boolean areRelated = child.getAbsolutePath().startsWith(parent.getAbsolutePath())
于 2013-08-14T09:24:44.733 回答