2015-01-31 41 views
0

這裏有兩個Java類:爲什麼這不正確地計算文件夾的總大小?

package je3.io; 

import java.io.File; 
import java.util.ArrayList; 
import java.util.List; 

/** 
* Created by IDEA on 31/01/15. 
*/ 
public class DirWalker { 
    private List<File> recursiveList = new ArrayList<File>(); 

    public void walkDir(String pathname) { 
     File d = new File(pathname); 
     recursiveList.add(d); 
     if(d.isDirectory()) { 
      for(String f : d.list()) { 
       walkDir(f); 
      } 
     } 
    } 

    public void reset() { 
     recursiveList.clear(); 
    } 

    public List<File> getRecursiveList() { 
     return recursiveList; 
    } 

    public static void main(String[] args) { 
     DirWalker dirWalker = new DirWalker(); 
     dirWalker.walkDir("/tmp"); 
     dirWalker.getRecursiveList().forEach(System.out::println); 
    } 
} 

package je3.io; 

import java.io.File; 

/** 
* Created by IDEA on 31/01/15. 
*/ 
public class DirSummariser { 
    private DirWalker dirWalker = new DirWalker(); 
    private long dirSize = 0; 

    public DirSummariser(String pathname) { 
     dirWalker.reset(); 
     dirWalker.walkDir(pathname); 
    } 

    public DirSummariser(File file) { 
     this(file.getAbsolutePath()); 
    } 

    public long calculateDirSize() { 
     for(File f : dirWalker.getRecursiveList()) { 
      dirSize += f.length(); 
     } 
     return dirSize; 
    } 

    public static void main(String[] args) { 
     DirSummariser dirSummariser = new DirSummariser("/Users/hualin/Downloads/pdf"); 
     System.out.println(dirSummariser.calculateDirSize()); 
    } 
} 

在第二類的主要方法,我試圖以計算PDF文件夾,它應該是大約30MB的總大小。 java程序編譯沒有錯誤,但是說文件夾的大小隻有1600字節。

+0

你不是用Java 7+嗎?如果是的話,那麼有更好的方法 – fge 2015-01-31 22:34:08

+0

是的,我使用的是java 8,但這是一種練習。 :-) – qed 2015-01-31 22:35:03

+0

那麼,使用Java 8就簡單多了。看看我的回答 – fge 2015-01-31 22:39:29

回答

3

的問題是在DirWalker

public void walkDir(String pathname) { 
    File d = new File(pathname); 
    recursiveList.add(d); 
    if(d.isDirectory()) { 
     for(String f : d.list()) { // <-- here 
      walkDir(f);    // <-- 
     } 
    } 
} 

通過d.list()返回的字符串是隻是文件名,不重視他們的路徑。例如,如果找到文件some_directory/foo.txt,則將從列表中取出的字符串爲foo.txt,並且由於foo.txt不在當前工作目錄中,因此您從中構建的File對象將無效(或描述不同的文件)。

你必須讓你想檢查遞歸的一部分,以使這項工作正確的路徑,例如像這樣:

  walkDir(pathname + File.separator + f); 

或者,如@Adam在評論中提到,通過將File對象描述的父目錄到遞歸和使用File(parent, child)構造,如

// new parameter here: parent directory 
public void walkDir(String pathname, File parent) { 
    System.out.println(pathname); 

    File d = new File(parent, pathname); // <-- File constructor with parent 
    recursiveList.add(d); 
    if(d.isDirectory()) { 
    for(String f : d.list()) { 
     walkDir(f, d);     // passing parent here 
    } 
    } 
} 

// entry point, to keep old interface. 
public void walkDir(String pathname) { 
    walkDir(pathname, null); 
} 

注:這個答案,我想這應該提到的是鐳因此我主要試圖解釋爲什麼他的代碼不起作用,並提出了使其工作的方法。如果你將來是一個流浪的訪問者,並想通過Java來瀏覽一個目錄,請看@fge的答案以獲得更好的方式。

+0

可以使用新的文件(父母,孩子),而不是搞亂連接... – Adam 2015-01-31 22:34:44

+0

@亞當我想是的,是的。我會把它放在那裏。 – Wintermute 2015-01-31 22:35:59

2

使用java.nio.file API,這樣做更好。

下面是一個例子,也使用throwing-lambdas,計算所有文件的總大小在一個目錄,遞歸:

final Path theDirectory = Paths.get("path/to/your/directory"); 

final long totalSize = Files.walk(theDirectory) 
    .filter(Files::isRegularFile) 
    .mapToLong(Functions.rethrow(Files::size)) 
    .sum(); 

如果您沒有安裝Java 8,使用Files.walkFileTree()