2010-08-26 27 views
12

Tôi đang có yêu cầu trong đó tôi phải tạo tệp zip từ danh sách các tệp khả dụng. Các tập tin có nhiều loại khác nhau như txt, pdf, xml vv. Tôi đang sử dụng các lớp java util để làm điều đó.Cách ước tính kích thước tệp zip trong java trước khi tạo nó

Yêu cầu ở đây là duy trì kích thước tệp tối đa là 5 mb. Tôi nên chọn các tệp từ danh sách dựa trên dấu thời gian, thêm tệp để nén cho đến khi kích thước tệp zip đạt đến 5 mb. Tôi nên bỏ qua các tập tin còn lại.

Vui lòng cho tôi biết nếu có cách nào trong java nơi tôi có thể ước tính kích thước tệp zip trước mà không cần tạo tệp thực?

Hoặc là có cách tiếp cận nào khác để xử lý này

Trả lời

0

Tôi không nghĩ rằng có bất cứ cách nào để ước tính kích thước của zip có sẽ được tạo ra vì kéo khóa được xử lý như suối. Ngoài ra, sẽ không thể dự đoán được kích thước của định dạng nén được tạo ra trừ khi bạn thực sự nén nó.

8

Đưa ZipOutputStream của bạn vào OutputStream được cá nhân hóa, có tên là YourOutputStream.

  • Các constructor của YourOutputStream sẽ tạo ra một ZipOutputStream (zos2) mà kết thúc tốt đẹp một mới ByteArrayOutputStream (baos)
    public YourOutputStream(ZipOutputStream zos, int maxSizeInBytes)
  • Khi bạn muốn viết một tập tin với YourOutputStream, nó sẽ lần đầu tiên viết nó trên zos2
    public void writeFile(File file) throws ZipFileFullException
    public void writeFile(String path) throws ZipFileFullException
    vv ...
  • nếu baos.size() là dưới maxSizeInBytes
    • Viết các tập tin trong zos1
  • khác
    • zos1 gần, baos, zos2 một ném một ngoại lệ. Đối với các trường hợp ngoại lệ, tôi không thể nghĩ ra một đã tồn tại, nếu có, sử dụng nó, khác tạo IOException ZipFileFullException của riêng bạn.

Bạn cần hai ZipOutputStream, một được viết trên ổ đĩa của bạn, một để kiểm tra xem nội dung của bạn là hơn 5MB.

EDIT: Trong thực tế, tôi đã kiểm tra, you can't remove a ZipEntry easily.

http://download.oracle.com/javase/6/docs/api/java/io/ByteArrayOutputStream.html#size()

+0

Cảm ơn tất cả vì sự giúp đỡ của bạn. Vì tôi chỉ cần kích thước thô và có thể tìm ra tỷ lệ nén cho hầu hết các loại tệp chúng tôi sử dụng, tôi đã sử dụng tỷ lệ nén do Nate đề xuất. Cảm ơn tất cả một lần nữa – Vignesh

0

Tôi đã thực hiện điều này một lần trên một dự án có các loại đầu vào đã biết. Chúng tôi biết rằng nói chung dữ liệu của chúng tôi nén khoảng 5: 1 (đó là tất cả văn bản.) Vì vậy, tôi muốn kiểm tra kích thước tập tin và chia cho 5 ...

Trong trường hợp này, mục đích để làm như vậy là kiểm tra xem các tệp có thể ở dưới một kích thước nhất định hay không. Chúng tôi chỉ cần một ước tính sơ bộ.

Tất cả những gì đã nói, tôi nhận thấy các ứng dụng zip như 7zip sẽ tạo một tệp zip có kích thước nhất định (như CD) và sau đó chia nhỏ tệp zip thành tệp mới sau khi đạt đến giới hạn. Bạn có thể xem mã nguồn đó.Tôi đã thực sự sử dụng phiên bản dòng lệnh của ứng dụng đó trong mã trước đây. Họ có một thư viện bạn có thể sử dụng là tốt. Không chắc chắn như thế nào mà sẽ tích hợp với Java mặc dù.

Đối với những gì đáng giá, tôi cũng đã sử dụng thư viện có tên là SharpZipLib. Nó là rất tốt. Tôi tự hỏi nếu có một cổng Java với nó.

1

+1 cho Colin Herbert: Thêm từng tệp một, hoặc sao lưu trước đó hoặc xóa tệp cuối cùng nếu lưu trữ lớn. Tôi chỉ muốn thêm một số chi tiết:

Dự đoán là quá đáng tin cậy. Ví dụ: một tệp PDF có thể chứa văn bản chưa nén và nén xuống 30% bản gốc hoặc có chứa văn bản và hình ảnh đã nén, nén tới 80%. Bạn sẽ cần phải kiểm tra toàn bộ PDF để nén, về cơ bản phải nén chúng.

Bạn có thể thử dự đoán thống kê, nhưng điều đó có thể giảm số lần thử không thành công, nhưng bạn vẫn phải triển khai đề xuất ở trên. Đi với việc thực hiện đơn giản đầu tiên, và xem nếu nó là đủ.

Cách khác, nén các tệp riêng lẻ, sau đó chọn tệp không vượt quá 5 MB nếu được liên kết với nhau. Nếu giải nén cũng được tự động, bạn có thể liên kết các tệp zip thành một tệp nén không nén duy nhất.

+0

Nếu thực tế điều này sẽ không thực sự hiệu quả, bạn có thể có tệp trên 5MB chỉ chứa "aaaa ...", nó sẽ được nén đủ để vừa với zip. –

+0

d'oh. Tôi có thể yêu cầu bồi thường vào sáng sớm không? – peterchen

+0

(cố định, tất nhiên) – peterchen

1

Có thể bạn có thể thêm tệp mỗi lần, cho đến khi bạn đạt đến giới hạn 5MB và sau đó loại bỏ tệp cuối cùng. Giống như @Gopi, tôi không nghĩ có cách nào để ước tính nó mà không thực sự nén tệp.

Tất nhiên, kích thước tệp sẽ không tăng (hoặc có thể một chút, do tiêu đề zip?), Vì vậy ít nhất bạn có ước tính "trường hợp xấu nhất".

+0

Xem "Yếu tố mở rộng tối đa" tại http://zlib.net/zlib_tech.html – snemarch

0

chỉ muốn chia sẻ cách thức chúng tôi thực hiện thủ công cách

  int maxSizeForAllFiles = 70000; // Read from property 
     int sizePerFile = 22000; // Red from property 
     /** 
     * Iterate all attachment list to verify if ZIP is required 
     */ 
     for (String attachFile : inputAttachmentList) { 
      File file = new File(attachFile); 
      totalFileSize += file.length(); 
      /** 
      * if ZIP required ??? based on the size 
      */ 
      if (file.length() >= sizePerFile) { 
       toBeZipped = true; 
       logger.info("File: " 
          + attachFile 
           + " Size: " 
           + file.length() 
           + " File required to be zipped, MAX allowed per file: " 
           + sizePerFile); 
       break; 
      } 
     } 
     /** 
     * Check if all attachments put together cross MAX_SIZE_FOR_ALL_FILES 
     */ 
     if (totalFileSize >= maxSizeForAllFiles) { 
      toBeZipped = true; 
     } 
     if (toBeZipped) { 
      // Zip Here iterating all attachments 
     } 
0

Có một lựa chọn tốt hơn. Tạo một hình nộm LengthOutputStream mà chỉ đếm byte viết:

public class LengthOutputStream extends OutputStream { 

    private long length = 0L; 

    @Override 
    public void write(int b) throws IOException { 
     length++; 
    } 

    public long getLength() { 
     return length; 
    } 
} 

Bạn có thể chỉ đơn giản là kết nối các LengthOutputStream đến một ZipOutputStream:

public static long sizeOfZippedDirectory(File dir) throws FileNotFoundException, IOException { 
     try (LengthOutputStream sos = new LengthOutputStream(); 
      ZipOutputStream zos = new ZipOutputStream(sos);) { 
      ... // Add ZIP entries to the stream 
      return sos.getLength(); 
     } 
    } 

Đối tượng LengthOutputStream đếm byte của con suối nhưng các cửa hàng nén gì cả, do đó không có giới hạn kích thước tệp. Phương pháp này đưa ra ước tính kích thước chính xác nhưng gần như chậm như việc tạo tệp ZIP.

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