2011-08-31 41 views
32

Làm cách nào tôi có thể nhận được kích thước của tệp hoặc thư mục bằng cách sử dụng NIO mới trong java 7?Nhận kích thước tệp/thư mục bằng cách sử dụng Java 7 new IO

+0

Có gì sai với cách cũ? Trừ khi có hỗ trợ cho kích thước thư mục đệ quy ngay bây giờ. Lanhung? – Thilo

+0

Tôi đã nghe nó nhanh hơn rất nhiều. và tôi muốn thử điều đó. – clamp

+0

Tôi phải tự hỏi làm thế nào nó có thể được nhanh hơn .. – Thilo

Trả lời

40

Sử dụng Files.size(Path) để lấy kích thước của tệp.

Đối với kích thước của một thư mục (nghĩa là kích thước của tất cả các tệp chứa trong thư mục), bạn vẫn cần phải recurse theo cách thủ công, theo như tôi biết.

+0

Tôi nghĩ rằng phương pháp trên không có trong Java7 I/O, Vui lòng kiểm tra một lần – developer

+1

@Damodar: câu trả lời của tôi chứa liên kết tới JavaDoc. Tại sao bạn nghĩ rằng nó không có mặt? –

+1

Ông liên kết với tài liệu API chính thức của Oracle. Phương pháp là có. – Thilo

5
MutableLong size = new MutableLong(); 
Files.walkFileTree(directoryPath, new SimpleFileVisitor<Path>() { 
      @Override 
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 
       size.add(attrs.size()); 
      } 
} 

Điều này sẽ tính toán kích thước của tất cả các tệp trong một thư mục. Tuy nhiên, lưu ý rằng tất cả các tệp trong thư mục cần phải là tệp thông thường, vì API chỉ định phương thức kích thước của BasicFileAttributes:

"Kích thước tệp không phải là tệp thông thường được triển khai cụ thể và do đó không xác định."

Nếu bạn vấp phải tệp không được kiểm soát, bạn sẽ có hoặc không bao gồm kích thước tệp hoặc trả về một số kích thước không xác định. Bạn có thể kiểm tra xem tệp có thường xuyên với

BasicFileAttributes.isRegularFile() 
+0

Câu trả lời hay, và đối với bất cứ ai tự hỏi các lớp Mutable * cho nguyên thủy là một phần của apache.commons.lang – Nicholi

6

Đây là ví dụ sẵn sàng chạy cũng sẽ bỏ qua và không thể nhập thư mục. Nó sử dụng java.util.concurrent.atomic.AtomicLong để tích lũy trạng thái.

public static void main(String[] args) throws IOException { 
    Path path = Paths.get("c:/"); 
    long size = getSize(path); 
    System.out.println("size=" + size); 
} 

static long getSize(Path startPath) throws IOException { 
    final AtomicLong size = new AtomicLong(0); 

    Files.walkFileTree(startPath, new SimpleFileVisitor<Path>() { 
     @Override 
     public FileVisitResult visitFile(Path file, 
       BasicFileAttributes attrs) throws IOException { 
      size.addAndGet(attrs.size()); 
      return FileVisitResult.CONTINUE; 
     } 

     @Override 
     public FileVisitResult visitFileFailed(Path file, IOException exc) 
       throws IOException { 
      // Skip folders that can't be traversed 
      System.out.println("skipped: " + file + "e=" + exc); 
      return FileVisitResult.CONTINUE; 
     } 
    }); 

    return size.get(); 
} 
+0

Tự hỏi tại sao 'AtomicLong' lại cần thiết? Tại sao không chỉ là một 'long'? Có điều gì đó song hành về [walkFileTree] không (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)? – peterh

+0

tbh, tôi chỉ viết lại câu trả lời khác mà không sử dụng 3pp (MutableLong). Nhưng tôi nghĩ rằng biến phải là "cuối cùng" để được truy cập từ lớp ẩn danh bên trong. AtomicLong cho phép. –

+0

Phương thức 'postVisitDirectory' cũng có thể được ghi đè lên. Không cần đánh dấu tham chiếu 'size' là cuối cùng ở đây vì nó không bị thay đổi trong lớp ẩn danh bên trong. Chỉ có nội dung (giá trị) của nó được thay đổi. Một mảng dài (với một phần tử duy nhất) có thể được sử dụng thay cho AtomicLong. – Stephan

Các vấn đề liên quan