Zlib压缩在Java中使用Deflate和Inflate类

我想尝试在java.util.zip中使用Deflate和Inflate类来进行zlib压缩。

我能够使用Deflate压缩代码,但在解压缩时,我遇到了这个错误 –

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) 

这是我目前的代码 –

 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"); } } 

你想在这做什么? 您使用InflaterInputStream解压缩数据,然后尝试将此解压缩数据再次传递给Inflater? 使用其中任何一个,但不能同时使用两个。

这就是造成你的例外的原因。

除此之外,还有一些小错误,比如bestsss提到的这些错误:

  • 您在循环中完成压缩 – 完成后,不能再添加数据。
  • 您不检查放气过程产生多少输出。 如果您有长行,则可能超过1024个字节。
  • 您也可以在不设置长度a情况下将输入设置到Inflater。

我发现了一些:

  • 写入后(以及从同一文件读取之前)不要关闭FileOutputStream。
  • 您使用readLine()读取一行文本,但之后不再添加换行符,这意味着在解压缩文件中不会有任何换行符。
  • 您无需任何需要将字节转换为字符串再转换为字节。
  • 您可以创建以后不使用的变量。

我不会尝试纠正你的程序。 这是一个使用DeflaterOutputStream和InflaterInputStream完成我认为你想要的东西。 (您也可以使用JZlib的ZInputStream和ZOutputStream。)

 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")); } } 

为了提高效率,使用缓冲流包装文件流可能很有用。 如果这是性能关键,请测量它。

使用try-with-resources可以进一步改善PaŭloEbermann的代码:

 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); } } }