2011-05-30 22 views
8

Tôi muốn cố gắng sử dụng các lớp Deflate và Inflate trong java.util.zip để nén zlib.Nén Zlib Sử dụng các lớp Deflate và Inflate trong Java

tôi có thể nén các mã sử dụng Deflate, nhưng khi giải nén, Tôi gặp lỗi này -

Exception in thread "main" java.util.zip.DataFormatException: unknown compression method 
    at java.util.zip.Inflater.inflateBytes(Native Method) 
    at java.util.zip.Inflater.inflate(Inflater.java:238) 
    at java.util.zip.Inflater.inflate(Inflater.java:256) 
    at zlibCompression.main(zlibCompression.java:53) 

Đây là mã của tôi cho đến nay -

import java.util.zip.*; 
import java.io.*; 

public class zlibCompression { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) throws IOException, DataFormatException { 
     // TODO Auto-generated method stub 

     String fname = "book1"; 
     FileReader infile = new FileReader(fname); 
     BufferedReader in = new BufferedReader(infile); 

     FileOutputStream out = new FileOutputStream("book1out.dfl"); 
     //BufferedInputStream in = new BufferedInputStream(new FileInputStream(filename)); 

     Deflater compress = new Deflater(); 
     Inflater decompress = new Inflater(); 

     String readFile = in.readLine(); 
     byte[] bx = readFile.getBytes(); 

     while(readFile!=null){ 
      byte[] input = readFile.getBytes(); 
      byte[] compressedData = new byte[1024]; 
      compress.setInput(input); 
      compress.finish(); 
      int compressLength = compress.deflate(compressedData, 0, compressedData.length); 
      //System.out.println(compressedData); 
      out.write(compressedData, 0, compressLength); 
      readFile = in.readLine(); 
     } 

     File abc = new File("book1out.dfl"); 
     InputStream is = new FileInputStream("book1out.dfl"); 

     InflaterInputStream infl = new InflaterInputStream(new FileInputStream("book1out.dfl"), new Inflater()); 
     FileOutputStream outFile = new FileOutputStream("decompressed.txt"); 

     byte[] b = new byte[1024]; 
     while(true){ 

      int a = infl.read(b,0,1024); 
      if(a==0) 
       break; 

      decompress.setInput(b); 
      byte[] fresult = new byte[1024]; 
      //decompress.in 
      int resLength = decompress.inflate(fresult); 
      //outFile.write(b,0,1); 
      //String outt = new String(fresult, 0, resLength); 
      //System.out.println(outt); 
     } 

     System.out.println("complete"); 

    } 
} 
+0

là một bài tập về nhà? một sai lầm là gọi kết thúc quá sớm, một người khác đang sử dụng setInput w/o chiều dài và một người khác không kiểm tra nếu quá trình deflate đã trả về nhiều dữ liệu hơn 1024. – bestsss

Trả lời

25

Bạn đang cố gắng để Làm ở đây? Bạn sử dụng một InflaterInputStream, giải nén dữ liệu của bạn, và sau đó bạn cố gắng chuyển dữ liệu giải nén này một lần nữa để một Inflater? Sử dụng một trong số họ, nhưng không phải cả hai.

Đây là nguyên nhân gây ra ngoại lệ của bạn tại đây.

Thêm vào đó, có khá một số lỗi nhỏ, như thế này được đề cập bởi bestsss:

  • Bạn hoàn tất việc nén trong vòng lặp - sau khi kết thúc, không có nhiều dữ liệu có thể được thêm vào.
  • Bạn không kiểm tra lượng đầu ra mà quá trình xì hơi tạo ra. Nếu bạn có đường dài, nó có thể nhiều hơn 1024 byte.
  • Bạn đặt đầu vào cho Inflater mà không cần cài đặt độ dài a.

Một số chi tiết mà tôi tìm thấy:

  • Bạn không đóng FileOutputStream của bạn sau khi văn bản (và trước khi đọc từ tập tin giống nhau).
  • Bạn sử dụng readLine() để đọc một dòng văn bản, nhưng sau đó bạn không thêm ngắt dòng một lần nữa, có nghĩa là trong tệp giải nén của bạn sẽ không bị ngắt dòng.
  • Bạn chuyển đổi từ byte thành chuỗi và thành byte một lần nữa mà không cần.
  • Bạn tạo các biến mà bạn không sử dụng sau này.

Tôi sẽ không cố sửa chương trình của bạn. Đây là một trong những đơn giản mà làm những gì tôi nghĩ rằng bạn muốn, bằng cách sử dụng DeflaterOutputStream và InflaterInputStream. (Bạn cũng có thể sử dụng ZInputStream và ZOutputStream JZlib của để thay thế.)

import java.util.zip.*; 
import java.io.*; 

/** 
* Example program to demonstrate how to use zlib compression with 
* Java. 
* Inspired by http://stackoverflow.com/q/6173920/600500. 
*/ 
public class ZlibCompression { 

    /** 
    * Compresses a file with zlib compression. 
    */ 
    public static void compressFile(File raw, File compressed) 
     throws IOException 
    { 
     InputStream in = new FileInputStream(raw); 
     OutputStream out = 
      new DeflaterOutputStream(new FileOutputStream(compressed)); 
     shovelInToOut(in, out); 
     in.close(); 
     out.close(); 
    } 

    /** 
    * Decompresses a zlib compressed file. 
    */ 
    public static void decompressFile(File compressed, File raw) 
     throws IOException 
    { 
     InputStream in = 
      new InflaterInputStream(new FileInputStream(compressed)); 
     OutputStream out = new FileOutputStream(raw); 
     shovelInToOut(in, out); 
     in.close(); 
     out.close(); 
    } 

    /** 
    * Shovels all data from an input stream to an output stream. 
    */ 
    private static void shovelInToOut(InputStream in, OutputStream out) 
     throws IOException 
    { 
     byte[] buffer = new byte[1000]; 
     int len; 
     while((len = in.read(buffer)) > 0) { 
      out.write(buffer, 0, len); 
     } 
    } 


    /** 
    * Main method to test it all. 
    */ 
    public static void main(String[] args) throws IOException, DataFormatException { 
     File compressed = new File("book1out.dfl"); 
     compressFile(new File("book1"), compressed); 
     decompressFile(compressed, new File("decompressed.txt")); 
    } 
} 

Để hiệu quả hơn, nó có thể có ích để bọc các con suối tập tin với suối đệm. Nếu đây là hiệu suất quan trọng, hãy đo lường nó. đang

+0

bạn có chắc chắn điều này là dành cho zlib hay không. Tôi cố gắng giải nén một tập tin zlib nhưng tôi nhận được một lỗi 'phương pháp nén chưa biết'. Nếu tôi nhìn vào http://docs.oracle.com/javase/1.4.2/docs/api/java/util/zip/package-summary.html thì tôi thấy 'Inflater' đề cập đến zlib nhưng bạn sử dụng' InflaterInputStream' đề cập deflate phương pháp nén. Đây là tệp: https://dl.dropboxusercontent.com/u/17630770/temp/pc_oj_simple_AnimTake1_11.icecache.zip – clankill3r

+0

InflaterInputStream sử dụng (nếu sử dụng hàm khởi tạo mà không có tham số Inflater) một 'new Inflater()'. Và hàm tạo này sử dụng 'nowrap = false', có nghĩa là nén zlib. (Tôi không kiểm tra tệp của bạn.) –

4

Paŭlo Ebermann 's có thể được cải thiện hơn nữa bằng cách sử dụng try-with-resources:

import java.util.Scanner; 
import java.util.zip.*; 
import java.io.*; 

public class ZLibCompression 
{ 
    public static void compress(File raw, File compressed) throws IOException 
    { 
     try (InputStream inputStream = new FileInputStream(raw); 
      OutputStream outputStream = new DeflaterOutputStream(new FileOutputStream(compressed))) 
     { 
      copy(inputStream, outputStream); 
     } 
    } 

    public static void decompress(File compressed, File raw) 
      throws IOException 
    { 
     try (InputStream inputStream = new InflaterInputStream(new FileInputStream(compressed)); 
      OutputStream outputStream = new FileOutputStream(raw)) 
     { 
      copy(inputStream, outputStream); 
     } 
    } 

    public static String decompress(File compressed) throws IOException 
    { 
     try (InputStream inputStream = new InflaterInputStream(new FileInputStream(compressed))) 
     { 
      return toString(inputStream); 
     } 
    } 

    private static String toString(InputStream inputStream) 
    { 
     try (Scanner scanner = new Scanner(inputStream).useDelimiter("\\A")) 
     { 
      return scanner.hasNext() ? scanner.next() : ""; 
     } 
    } 

    private static void copy(InputStream inputStream, OutputStream outputStream) 
      throws IOException 
    { 
     byte[] buffer = new byte[1000]; 
     int length; 

     while ((length = inputStream.read(buffer)) > 0) 
     { 
      outputStream.write(buffer, 0, length); 
     } 
    } 
} 
+0

Mục tiêu của máy quét là gì? Chỉ nhận được dòng đầu tiên của luồng? –

+1

@ Paŭlo Ebermann: Đây là mẹo để đọc toàn bộ luồng cùng một lúc – BullyWiiPlaza

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