Java 检查文件是否在(子)目录中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18227634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if file is in (sub)directory
提问by Johannes Dorn
I would like to check whether an existing file is in a specific directory or a subdirectory of that.
我想检查现有文件是否在特定目录或该目录的子目录中。
I have two File objects.
我有两个 File 对象。
File dir;
File file;
Both are guaranteed to exist. Let's assume
两者都保证存在。让我们假设
dir = /tmp/dir
file = /tmp/dir/subdir1/subdir2/file.txt
I want this check to return true
我希望此检查返回 true
For now i am doing the check this way:
现在我正在以这种方式进行检查:
String canonicalDir = dir.getCanonicalPath() + File.separator;
boolean subdir = file.getCanonicalPath().startsWith(canonicalDir);
This seems to work with my limited tests, but i am unsure whether this might make problems on some operating systems. I also do not like that getCanonicalPath() can throw an IOException which i have to handle.
这似乎适用于我有限的测试,但我不确定这是否会在某些操作系统上产生问题。我也不喜欢 getCanonicalPath() 可以抛出一个我必须处理的 IOException 。
Is there a better way? Possibly in some library?
有没有更好的办法?可能在某个图书馆?
Thanks
谢谢
回答by rocketboy
How about comparing the paths?
如何比较路径?
boolean areRelated = file.getAbsolutePath().contains(dir.getAbsolutePath());
System.out.println(areRelated);
or
或者
boolean areRelated = child.getAbsolutePath().startsWith(parent.getAbsolutePath())
回答by Luca Basso Ricci
If you plan to works with file and filenames heavly check apache fileutils and filenameutils libraries. Are full of useful (and portale if portability is mamdatory) functions
如果您打算使用文件和文件名,请检查 apache fileutils 和 filenameutils 库。充满了有用的(如果可移植性是必需的,则是门户)功能
回答by r3ap3r
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();
}
}
}
}
回答by dacwe
I would create a small utility method:
我会创建一个小的实用方法:
public static boolean isInSubDirectory(File dir, File file) {
if (file == null)
return false;
if (file.equals(dir))
return true;
return isInSubDirectory(dir, file.getParentFile());
}
回答by michal
You can traverse File Tree starting from your specific DIR.
At Java 7, there is Files.walkFileTree
method. You have only to write your own visitor
to check if current node is searched file. More doc:
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
您可以从您的特定 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
回答by Jorge Fuentes González
In addition to the asnwer from rocketboy, use getCanonicalPath()
instad of getAbsolutePath()
so \dir\dir2\..\file
is converted to \dir\file
:
除了来自 Rocketboy 的 asnwer 之外,使用getCanonicalPath()
instad getAbsolutePath()
so\dir\dir2\..\file
转换为\dir\file
:
boolean areRelated = file.getCanonicalPath().contains(dir.getCanonicalPath() + File.separator);
System.out.println(areRelated);
or
或者
boolean areRelated = child.getCanonicalPath().startsWith(parent.getCanonicalPath() + File.separator);
Do not forget to catch any Exception
with try {...} catch {...}
.
不要忘记抓住任何Exception
与try {...} catch {...}
。
NOTE: You can use FileSystem.getSeparator()
instead of File.separator
. The 'correct' way of doing this will be to get the getCanonicalPath()
of the directory that you are going to check against as a String
, then check if ends with a File.separator
and if not then add File.separator
to the end of that String
, to avoid double slashes. This way you skip future odd behaviours if Java decides to return directories with a slash in the end or if your directory string comes from somewhere else than Java.io.File
.
注意:您可以使用FileSystem.getSeparator()
代替File.separator
. 这样做的“正确”方法是获取getCanonicalPath()
您要检查的目录的 a String
,然后检查是否以 a 结尾,File.separator
如果不是,则添加File.separator
到 a 的末尾String
,以避免双斜杠。这样,如果 Java 决定以斜杠结尾返回目录,或者如果您的目录字符串来自Java.io.File
.
NOTE2: Thanx to @david for pointing the File.separator
problem.
注2:感谢@david 指出File.separator
问题。
回答by tsauerwein
This method looks pretty solid:
这个方法看起来很可靠:
/**
* 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;
}
It is similar to the solution by dacwe but doesn't use recursion (though that shouldn't make a big difference in this case).
它类似于 dacwe 的解决方案,但不使用递归(尽管在这种情况下应该没有太大区别)。
回答by ManoDestra
You can do this, however it won't catch every use case e.g. dir = /somedir/../tmp/dir/etc..., unless that's how the file was defined also.
您可以这样做,但是它不会捕获每个用例,例如 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);
}
}
In order for the checks to work correctly, you really need to map these using toRealPath()
or, in your example, getCanonicalPath()
, but you then have to handle exceptions for these examples which is absolutely correct that you should do so.
为了使检查正常工作,您确实需要使用toRealPath()
或 在您的示例中映射这些getCanonicalPath()
,但是您必须处理这些示例的异常,您应该这样做是绝对正确的。