我的程序将计算机上的所有文件路径(OS Ubuntu)收集到一个 Map 。 Map 中的键是文件大小,值是文件的规范路径列表,大小等于key。
Map<Long, ArrayList<String>> map = new HashMap<>(100000);
计算机上的文件总数为: 281091
收集文件的方法,它是递归的。
private void scanner(String path) throws Exception {
File[] dirs = new File(path).listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isFile() && file.canRead()) {
long size = file.length();
String canonPath = file.getCanonicalPath();
if (map.containsKey(size))
map.get(size).add(canonPath);
else map.put(size, new ArrayList<>(Arrays.asList(canonPath)));
return false;
}
return file.isDirectory() && file.canRead();
}
});
for (File dir : dirs) {
scanner(dir.getCanonicalPath());
}
}
当我开始从根文件夹开始扫描时,“/”有异常:
Exception in thread "main" java.lang.StackOverflowError
at java.io.UnixFileSystem.canonicalize0(Native Method)
at java.io.UnixFileSystem.canonicalize(UnixFileSystem.java:172)
at java.io.File.getCanonicalPath(File.java:589)
at taskB.FileScanner.setCanonPath(FileScanner.java:49)
at taskB.FileScanner.access$000(FileScanner.java:12)
at taskB.FileScanner$1.accept(FileScanner.java:93)
at java.io.File.listFiles(File.java:1217)
at taskB.FileScanner.scanner(FileScanner.java:85)
at taskB.FileScanner.scanner(FileScanner.java:109)
at taskB.FileScanner.scanner(FileScanner.java:109)
...
但是对于测试我填写目录“〜/ Documents”超过 400 〜千个文件并开始从中扫描。一切正常。
为什么当程序从根目录“/”开始时,我的异常少了30万个文件?我应该怎么做才能防止这种情况发生?
答案 0 :(得分:1)
StackOverflow意味着您调用了如此多的嵌套函数,使得程序在内存空间中用尽函数调用信息(从调用返回后保留)。在你的情况下,我怀疑这是由于解析“。” (当前目录)和“..”(父目录)条目在目录列表中返回时,因此您可以多次递归到同一目录。
答案 1 :(得分:1)
最可能的解释是,在文件系统中的某处创建一个符号链接,创建一个循环(无限循环)。例如,以下是一个循环
/home/userid/test/data -> /home/userid
扫描文件时,您需要忽略指向目录的符号链接。
答案 2 :(得分:1)
我使用isSymbolicLink(Path)方法。
return file.isDirectory() && file.canRead() && !Files.isSymbolicLink(file.toPath());