我写了一个小函数来计算目录中所有文件的大小。实际的功能做得更多,但这个例子用于简洁。
这是可行的,并且递归地遍历目录很容易,但我想排除已经处理过的所有文件名。我想跟踪List
中的所有文件名,以便在获取文件大小之前,检查它是否存在于List
中,如果存在,则应将其排除。我不想要任何MD5校验和或任何东西。文件名对我的情况来说已经足够了。
由于我只能从函数返回一个值而Java不允许传递引用,所以我很遗憾实现它的最佳方法是什么。这是我的代码:
public static Long getFileSize(File dirDirectory) {
Long lngSize = new Long(0);
for (File filItem : dirDirectory.listFiles()) {
if (filItem.isDirectory()) {
lngSize += getFileSize(filItem);
}
else {
//Is a file with the same filename alrwady been calculated
//then exclude it
//else
//include it.
lngSize += filItem.length();
}
}
return lngSize;
}
答案 0 :(得分:3)
请勿使用List
,请使用HashSet
。列表将使用O(n)
查找来查看文件是否存在,而HashSet
将使用O(1)
。
通过将方法设为public并将辅助函数设为私有,您不会将HashSet
实现暴露给程序的其余部分(它不会也不应该关心它)。
public static Long getFileSize(File dirDirectory) {
return getFileSize(File dirDirectory, new HashSet<File>());
}
private static Long getFileSize(File dirDirectory, HashSet<File> prevProcess) {
Long lngSize = new Long(0);
for (File filItem : dirDirectory.listFiles()) {
if (prevProcess.contains(filItem) continue;
if (filItem.isDirectory()) {
lngSize += getFileSize(filItem);
}
else {
lngSize += filItem.length();
}
prevProcess.add(filItem);
}
return lngSize;
}
答案 1 :(得分:1)
你可以这样做:
public static Long getFileSize(File dirDirectory) {
return getFileSize(dirDirectory, new HashSet<String>());
}
public static Long getFileSize(File dirDirectory, Set<String> previouslyProcessedFiles) {
//DO IT HERE AS YOU WISH
}
答案 2 :(得分:0)
传递一个Set:
public static Long getFileSize(Set<File> alreadySeen, File dirDirectory) {
long lngSize = 0;
for (File filItem : dirDirectory.listFiles()) {
if (filItem.isDirectory()) {
lngSize += getFileSize(filItem);
}
else {
//Is a file with the same filename alrwady been calculated
//then exclude it
//else
//include it.
if (! alreadySeen.contains(filItem.getName())) {
alreadySeen.add(filItem.getName());
lngSize += filItem.length();
}
}
}
return lngSize;
}
致电:
Long size = getFileSize(new HashSet<File>(), myDirectory)
此外,您最好使用long
计数器而非Long
,以避免Java需要不断取消装箱/重新装箱。
顺便说一句,在没有递归的情况下遍历目录树很简单,只需将您遇到的目录添加到稍后要处理的列表中:
public static Long getFileSize(File dirDirectory) {
long lngSize = 0;
Deque<File> unprocessedDirs = new ArrayDeque<File>();
unprocessedDirs.add(dirDirectory);
Set<File> alreadySeen = new HashSet<File>();
while (!unprocessedDirs.isEmpty()) {
File dir = unprocessedDirs.removeFirst();
for (File filItem : dir.listFiles()) {
if (filItem.isDirectory()) {
unprocessedDirs.addFirst(filItem);
}
else {
//Is a file with the same filename alrwady been calculated
//then exclude it
//else
//include it.
if (! alreadySeen.contains(filItem.getName())) {
alreadySeen.add(filItem.getName());
lngSize += filItem.length();
}
}
}
}
return lngSize;
}
答案 3 :(得分:0)
这个怎么样:
public static Long getFileSize(File dirDirectory, List<String> processed) {
Long lngSize = new Long(0);
for (File filItem : dirDirectory.listFiles()) {
if (filItem.isDirectory()) {
lngSize += getFileSize(filItem, processed);
} else {
String filName = filItem.getName();
if (processed.contains(filName)) {
continue;
}
lngSize += filItem.length();
processed.add(filName);
}
}
return lngSize;
}
答案 4 :(得分:0)
您可以使用全局变量或将列表作为参数传递给函数。 但我的建议不是使用List,而是使用Set,特别是TreeSet或HashSet。
您不需要存储重复项,并且您必须在完整列表中搜索文件名 - 在列表O(n)中非常昂贵的操作。一个集合将防止重复,但特别是HashSet是O(n)而TreeSet是O(ln n) - 使搜索更快
答案 5 :(得分:0)
我建议您使用内置过滤器FileFilter
或FilenameFilter
和File.listFiles()
方法。这样它更优雅,更直观。
public class FileSizeCalculator {
public static void main(String[] args) {
System.out.println(getFileSize(new File(".")));
}
public static Long getFileSize(File directory) {
FileFilter uniqueFilter = new FileFilter() {
Set<File> uniqueFiles = new HashSet<File>();
@Override
public boolean accept(File file) {
/**
* This will return true only if this set
* did not already contain the specified element
*/
return uniqueFiles.add(file);
}
};
long size = 0L;
for (File file : directory.listFiles(uniqueFilter)) {
size += file.isDirectory() ? getFileSize(file) : file.length();
}
return size;
}
}