Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检查文件是否在(子)目录中_Java - Fatal编程技术网

Java 检查文件是否在(子)目录中

Java 检查文件是否在(子)目录中,java,Java,我想检查现有文件是否位于特定目录或其子目录中 我有两个文件对象 File dir; File file; 两者都保证存在。让我们假设 dir = /tmp/dir file = /tmp/dir/subdir1/subdir2/file.txt 我希望这张支票是真的 现在我是这样做的: String canonicalDir = dir.getCanonicalPath() + File.separator; boolean subdir = file.getCanonicalPath(

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

我有两个文件对象

File dir;
File file;
两者都保证存在。让我们假设

dir  = /tmp/dir 
file = /tmp/dir/subdir1/subdir2/file.txt
我希望这张支票是真的

现在我是这样做的:

String canonicalDir = dir.getCanonicalPath() + File.separator;
boolean subdir = file.getCanonicalPath().startsWith(canonicalDir);
这似乎适用于我有限的测试,但我不确定这是否会在某些操作系统上产生问题。我也不喜欢getCanonicalPath()可以抛出我必须处理的IOException

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


谢谢

比较一下路径怎么样

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


如果您计划使用文件和文件名,请仔细检查apache fileutils和filenameutils库。有很多有用的功能(如果可移植性很重要的话,还可以移植)

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();
    }
}

}

我将创建一个小型实用方法:

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

    if (file == null)
        return false;

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

    return isInSubDirectory(dir, file.getParentFile());
}

您可以从特定目录开始遍历文件树。 在Java7中,有
Files.walkFileTree
方法。你只需要写你自己的访客 检查当前节点是否已在文件中搜索。更多文件:

除了rocketboy提供的asnwer外,还可以使用
getCanonicalPath()
instad of
getAbsolutePath()
\dir\dir2\..\file
转换为
\dir\file

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

不要忘记用
try{…}catch{…}
捕获任何
异常

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


注2:Thanx指向@david,用于指向
文件.separator
问题。

此方法看起来非常可靠:

/**
 * 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的解决方案,但不使用递归(尽管在这种情况下,递归不会有很大的区别)。

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

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()
或在您的示例中使用
getCanonicalPath()
来映射这些检查,但是您必须处理这些示例的异常,这是绝对正确的。对于包含以下内容的路径,这可能会有问题“/tmp/something/./dir”在我的应用程序中是可能的。您可以很容易地使用
child.getAbsolutePath().startsWith(parent.getAbsolutePath())
如果是这样的话。实际上getAbsolutePath()将计算所有这样的“/../”标记,并在文件系统中返回真正的绝对路径。恐怕不能:
新文件(“/Users/johndoe/test/./dir”).getAbsolutePath()
返回
“/Users/johndoe/test/./dir”
您至少需要使用
getCanonicalFile()
!那
/a
/ab/test.txt
呢?@david将返回完全相同的结果。如果您要求使用斜杠而不是反斜杠,我不知道其行为,但我的建议是使用OS native。Java有一个返回OS native目录分隔符的函数,但我现在不记得了。我的观点不是关于目录斜杠的一部分;我给出了一个反例,使用你的答案中的策略会导致错误的答案。@david,这就是为什么我说你必须使用操作系统固有的斜杠。如果你编程好了,你总是要清理用户输入。如果你仔细看,你会注意到我调用了
getCanonicalPath()
Java.io.File
上,因此显然我假设
Java.io.File
是一个有效的文件,因为我的答案来自
[…]检查现有文件[…]
。检查该文件是否有效/现有文件的工作(非空文本/使用Java本机函数查找文件/检查本机操作系统斜杠(当用户直接输入文本时)/等…)程序员在这里工作吗?你又没抓住重点。是
/ab/test.txt
/a
的子目录中吗?想想看。我会先检查文件是否是一个文件。但可能不是。这听起来是个好主意,但应该是一个更大的解决方案的一部分。它对我有效。我会两次投票赞成使用n关于递归方法
/**
 * 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;
}
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);
    }
}