2010-01-27 34 views

Trả lời

158
java.io.File file = new java.io.File("myfile.txt"); 
file.length(); 

này trả về chiều dài của tập tin trong byte hoặc 0 nếu tập tin không tồn tại. Không có cách tích hợp để lấy kích cỡ của thư mục, bạn sẽ phải theo dõi thư mục một cách đệ quy (sử dụng phương thức listFiles() của đối tượng tệp đại diện cho thư mục) và tích lũy kích thước thư mục cho mình:

public static long folderSize(File directory) { 
    long length = 0; 
    for (File file : directory.listFiles()) { 
     if (file.isFile()) 
      length += file.length(); 
     else 
      length += folderSize(file); 
    } 
    return length; 
} 

CẢNH BÁO: Phương pháp này không đủ mạnh để sử dụng sản xuất. directory.listFiles() có thể trả lại null và gây ra NullPointerException. Ngoài ra, nó không xem xét các liên kết tượng trưng và có thể có các chế độ lỗi khác. Sử dụng this method.

+19

1 như thế này đã sẵn sàng để chạy các ví dụ – stacker

+11

Hãy cẩn thận nếu bạn chạy nó trong thư mục gốc C: trên máy Windows; có một tệp hệ thống ở đó (theo java.io.File) không phải là một tệp hay một thư mục. Bạn có thể muốn thay đổi mệnh đề else để kiểm tra xem File có thực sự là một thư mục hay không. –

+2

Thay đổi đơn giản để kiểm tra tham số để xem nếu nó không phải là thư mục ở đầu phương thức và trả về độ dài thì đệ quy đơn giản hơn - chỉ cần thêm cuộc gọi vào chính phương thức đó và sau đó hỗ trợ truyền trong tham chiếu tệp thay vì thư mục. –

3

File.length() (Javadoc).

Lưu ý rằng thao tác này không hoạt động đối với các thư mục hoặc không được bảo đảm hoạt động.

Đối với một thư mục, bạn muốn gì? Nếu đó là tổng kích thước của tất cả các tệp bên dưới, bạn có thể đệ quy đệ trình trẻ em bằng cách sử dụng File.list()File.isDirectory() và tính tổng kích thước của chúng.

3

Đối tượng File có một phương pháp length:

f = new File("your/file/name"); 
f.length(); 
10
public static long getFolderSize(File dir) { 
    long size = 0; 
    for (File file : dir.listFiles()) { 
     if (file.isFile()) { 
      System.out.println(file.getName() + " " + file.length()); 
      size += file.length(); 
     } 
     else 
      size += getFolderSize(file); 
    } 
    return size; 
} 
+1

@Cần mã của bạn cần phải sửa chữa đơn giản, trong cuộc gọi đệ quy, bạn nên thêm kích thước vào kích thước hiện tại không chỉ gán cho nó. 'size + = getFolderSize (tập tin);' –

+0

@Teja: Cảm ơn bạn đã chỉ ra, nhưng những thay đổi sẽ có trong câu lệnh if – Vishal

+0

Đôi khi trên thư mục * đang phát triển * (một chủ đề khác đang tải xuống tệp và thư mục và tại đồng thời tôi đang in kích thước thư mục như tiến trình) nó cho ** nullpointerexception ** tại dòng "cho (File file: dir.listFiles()) {". Một số tệp xuất hiện và biến mất nhanh chóng trên một thư mục đang hoạt động. Vì vậy, tôi đã thêm một kiểm tra null cho * dir.listFiles() * trả về giá trị trước cho vòng lặp. – csonuryilmaz

29

Bạn cần FileUtils#sizeOfDirectory(File) từ commons-io.

Lưu ý rằng bạn sẽ cần phải kiểm tra thủ công xem tệp có phải là một thư mục hay không khi phương thức này ném ngoại lệ nếu một thư mục không được chuyển đến thư mục đó.

CẢNH BÁO: Phương pháp này (như của commons-io 2.4) có lỗi và có thể ném IllegalArgumentException nếu thư mục được đồng thời sửa đổi.

+0

Vậy điều gì xảy ra khi tệp không phải là một thư mục? khi nó không tồn tại? v.v. - tài liệu khủng khiếp như thế nào –

+0

@Mr_and_Mrs_D - Chỉ cần sao chép và dán các dòng sau khi kiểm tra 'checkDirectory (thư mục);' kiểm tra. Chỉ cần đảm bảo rằng 'File.listFiles' có con. ** Tham khảo: ** [FileUtils.sizeOfDirectory()] (http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/2.4/org/apache/commons/io/ FileUtils.java # FileUtils.sizeOfDirectory% 28java.io.File% 29), [File.listFiles()] (http://docs.oracle.com/javase/6/docs/api/java/io/File.html #listFiles) –

+2

Xem lỗi [IO-449] (https://issues.apache.org/jira/browse/IO-449). Phương thức này sẽ ném một 'IllegalArgumentException' nếu thư mục được sửa đổi trong khi nó đang lặp lại. –

27

Sử dụng java-7 nio api, việc tính kích thước thư mục có thể được thực hiện nhanh hơn rất nhiều.

Dưới đây là ví dụ đã sẵn sàng để chạy mạnh mẽ và sẽ không ném ngoại lệ. Nó sẽ đăng nhập các thư mục mà nó không thể nhập hoặc gặp sự cố khi di chuyển. Các liên kết bị bỏ qua và việc sửa đổi đồng thời thư mục sẽ không gây ra nhiều rắc rối hơn mức cần thiết.

/** 
* Attempts to calculate the size of a file or directory. 
* 
* <p> 
* Since the operation is non-atomic, the returned value may be inaccurate. 
* However, this method is quick and does its best. 
*/ 
public static long size(Path path) { 

    final AtomicLong size = new AtomicLong(0); 

    try { 
     Files.walkFileTree(path, new SimpleFileVisitor<Path>() { 
      @Override 
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { 

       size.addAndGet(attrs.size()); 
       return FileVisitResult.CONTINUE; 
      } 

      @Override 
      public FileVisitResult visitFileFailed(Path file, IOException exc) { 

       System.out.println("skipped: " + file + " (" + exc + ")"); 
       // Skip folders that can't be traversed 
       return FileVisitResult.CONTINUE; 
      } 

      @Override 
      public FileVisitResult postVisitDirectory(Path dir, IOException exc) { 

       if (exc != null) 
        System.out.println("had trouble traversing: " + dir + " (" + exc + ")"); 
       // Ignore errors traversing a folder 
       return FileVisitResult.CONTINUE; 
      } 
     }); 
    } catch (IOException e) { 
     throw new AssertionError("walkFileTree will not throw IOException if the FileVisitor does not"); 
    } 

    return size.get(); 
} 
+0

Có tương đương với điều này trên phát triển Android không? –

+0

Có lý do nào để sử dụng 'AtomicLong' thay vì chỉ 'long'? –

+0

Biến này phải là cuối cùng khi được truy cập từ lớp ẩn danh –

8

Trong Java 8:

long size = Files.walk(path).mapToLong(p -> p.toFile().length()).sum(); 

Nó sẽ đẹp hơn để sử dụng Files::size trong bước bản đồ nhưng nó ném một ngoại lệ kiểm tra.

CẬP NHẬT:
Bạn cũng nên lưu ý rằng điều này có thể ném ngoại lệ nếu một số tệp/thư mục không thể truy cập được. Xem điều này question và một giải pháp khác bằng cách sử dụng Guava.

+1

tôi đã xem xét một cái gì đó tương tự và kết thúc với mã trong câu hỏi: http://stackoverflow.com/questions/22867286/ files-walk-calculate-total-size, như bạn thấy có một khía cạnh khác của xử lý lỗi cũng gây ra vấn đề. –

+0

@AkselWillgert Cảm ơn, đây là điều không may và tôi đã cập nhật câu trả lời. Bây giờ chuyển sang ổi http://stackoverflow.com/a/24757556/1180621 – Andrejs

2

Dưới đây là cách tốt nhất để có được kích thước một file chung của (chỉ hoạt động cho thư mục và không thư mục):

public static long getSize(File file) { 
    long size; 
    if (file.isDirectory()) { 
     size = 0; 
     for (File child : file.listFiles()) { 
      size += getSize(child); 
     } 
    } else { 
     size = file.length(); 
    } 
    return size; 
} 

Chỉnh sửa: Lưu ý rằng đây có lẽ sẽ là một hoạt động tốn nhiều thời gian. Đừng chạy nó trên chuỗi giao diện người dùng.

Ngoài ra, ở đây (lấy từ https://stackoverflow.com/a/5599842/1696171) là một cách tốt đẹp để có được một chuỗi người dùng có thể đọc được từ trở lại dài:

public static String getReadableSize(long size) { 
    if(size <= 0) return "0"; 
    final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; 
    int digitGroups = (int) (Math.log10(size)/Math.log10(1024)); 
    return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups)) 
      + " " + units[digitGroups]; 
} 
0
public long folderSize (String directory) 
    { 
     File curDir = new File(directory); 
     long length = 0; 
     for(File f : curDir.listFiles()) 
     { 
      if(f.isDirectory()) 
      {    
       for (File child : f.listFiles()) 
       { 
        length = length + child.length(); 
       } 

       System.out.println("Directory: " + f.getName() + " " + length + "kb"); 
      } 
      else 
      { 
       length = f.length(); 
       System.out.println("File: " + f.getName() + " " + length + "kb"); 
      } 
      length = 0; 
     } 
     return length; 
    } 
0

Sau rất nhiều nghiên cứu và tìm kiếm các giải pháp khác nhau đề xuất ở đây tại StackOverflow. Cuối cùng tôi quyết định viết giải pháp của riêng mình. Mục đích của tôi là có cơ chế không ném vì tôi không muốn gặp sự cố nếu API không thể tìm nạp kích thước thư mục. Phương pháp này không phù hợp với kịch bản nhiều luồng.

Trước hết, tôi muốn kiểm tra các thư mục hợp lệ trong khi duyệt qua cây hệ thống tệp.

private static boolean isValidDir(File dir){ 
    if (dir != null && dir.exists() && dir.isDirectory()){ 
     return true; 
    }else{ 
     return false; 
    } 
} 

Thứ hai Tôi không muốn lời gọi đệ quy của tôi đi vào liên kết tượng trưng (liên kết mềm) và bao gồm tổng kích thước trong tổng số.

public static boolean isSymlink(File file) throws IOException { 
    File canon; 
    if (file.getParent() == null) { 
     canon = file; 
    } else { 
     canon = new File(file.getParentFile().getCanonicalFile(), 
       file.getName()); 
    } 
    return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); 
} 

Cuối cùng đệ quy dựa trên việc triển khai của tôi để tìm nạp kích thước của thư mục được chỉ định. Chú ý kiểm tra null cho dir.listFiles(). Theo javadoc, có khả năng phương thức này có thể trả về null.

public static long getDirSize(File dir){ 
    if (!isValidDir(dir)) 
     return 0L; 
    File[] files = dir.listFiles(); 
    //Guard for null pointer exception on files 
    if (files == null){ 
     return 0L; 
    }else{ 
     long size = 0L; 
     for(File file : files){ 
      if (file.isFile()){ 
       size += file.length(); 
      }else{ 
       try{ 
        if (!isSymlink(file)) size += getDirSize(file); 
       }catch (IOException ioe){ 
        //digest exception 
       } 
      } 
     } 
     return size; 
    } 
} 

Một số kem trên bánh, API để lấy kích thước của danh sách Tệp (có thể là tất cả các tệp và thư mục dưới gốc).

public static long getDirSize(List<File> files){ 
    long size = 0L; 
    for(File file : files){ 
     if (file.isDirectory()){ 
      size += getDirSize(file); 
     } else { 
      size += file.length(); 
     } 
    } 
    return size; 
} 
2

Đối Java 8 đây là một cách đúng đắn để làm điều đó:

Files.walk(new File("D:/temp").toPath()) 
       .map(f -> f.toFile()) 
       .filter(f -> f.isFile()) 
       .mapToLong(f -> f.length()).sum() 

Điều quan trọng là để lọc ra tất cả các thư mục, bởi vì phương pháp chiều dài không đảm bảo được 0 cho các thư mục.

Ít nhất mã này cung cấp cùng một thông tin kích thước như bản thân Windows Explorer.

2

Nếu bạn muốn sử dụng Java 8 nio API, chương trình sau đây sẽ in kích thước, tính theo byte, của thư mục nó nằm trong.

import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 

public class PathSize { 

    public static void main(String[] args) { 
     Path path = Paths.get("."); 
     long size = calculateSize(path); 
     System.out.println(size); 
    } 

    /** 
    * Returns the size, in bytes, of the specified <tt>path</tt>. If the given 
    * path is a regular file, trivially its size is returned. Else the path is 
    * a directory and its contents are recursively explored, returning the 
    * total sum of all files within the directory. 
    * <p> 
    * If an I/O exception occurs, it is suppressed within this method and 
    * <tt>0</tt> is returned as the size of the specified <tt>path</tt>. 
    * 
    * @param path path whose size is to be returned 
    * @return size of the specified path 
    */ 
    public static long calculateSize(Path path) { 
     try { 
      if (Files.isRegularFile(path)) { 
       return Files.size(path); 
      } 

      return Files.list(path).mapToLong(PathSize::calculateSize).sum(); 
     } catch (IOException e) { 
      return 0L; 
     } 
    } 

} 

Phương pháp calculateSize là phổ quát cho Path đối tượng , vì vậy nó cũng hoạt động cho các tập tin. Lưu ý rằng nếu một tệp hoặc thư mục không thể truy cập được, trong trường hợp này, kích thước trả về của đối tượng đường dẫn sẽ là 0.

0

trong linux nếu bạn muốn sắp xếp thư mục sau đó du -hs * | loại -h

1
  • trình cho AndroidJava
  • trình cho cả các thư mục và các tập tin
  • Kiểm tra cho con trỏ null ở khắp mọi nơi khi cần
  • Bỏ qua symbolic link aka phím tắt
  • sản xuất sẵn sàng ! đang

Nguồn:

public long fileSize(File root) { 
     if(root == null){ 
      return 0; 
     } 
     if(root.isFile()){ 
      return root.length(); 
     } 
     try { 
      if(isSymlink(root)){ 
       return 0; 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return 0; 
     } 

     long length = 0; 
     File[] files = root.listFiles(); 
     if(files == null){ 
      return 0; 
     } 
     for (File file : files) { 
      length += fileSize(file); 
     } 

     return length; 
    } 

    private static boolean isSymlink(File file) throws IOException { 
     File canon; 
     if (file.getParent() == null) { 
      canon = file; 
     } else { 
      File canonDir = file.getParentFile().getCanonicalFile(); 
      canon = new File(canonDir, file.getName()); 
     } 
     return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); 
    } 
Các vấn đề liên quan