2013-02-08 158 views
10

我想寫一個可以壓縮數據的類。下面的代碼失敗(不會引發異常,但目標.gz文件爲空)。
此外:我不想直接生成.gz文件,因爲它在所有示例中都是這樣。我只想得到壓縮的 數據,以便我可以例如在將數據寫入文件之前對其進行加密。GZIP壓縮到一個字節數組

如果我直接寫一個文件,一切工作正常:

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

public class Zipper 
{ 
    public static void main(String[] args) 
    {  
    byte[] dataToCompress = "This is the test data." 
     .getBytes(StandardCharsets.ISO_8859_1); 

    GZIPOutputStream zipStream = null; 
    FileOutputStream fileStream = null; 
    try 
    { 
     fileStream = new FileOutputStream("C:/Users/UserName/Desktop/zip_file.gz"); 
     zipStream = new GZIPOutputStream(fileStream); 
     zipStream.write(dataToCompress); 

     fileStream.write(compressedData); 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    finally 
    { 
     try{ zipStream.close(); } 
     catch(Exception e){ } 
     try{ fileStream.close(); } 
     catch(Exception e){ } 
    } 
    } 
} 

但是,如果我想「旁路」它的字節數組流也不會產生一個單字節 - compressedData總是空。

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

public class Zipper 
{ 
    public static void main(String[] args) 
    {  
    byte[] dataToCompress = "This is the test data." 
     .getBytes(StandardCharsets.ISO_8859_1); 
    byte[] compressedData = null; 

    GZIPOutputStream zipStream = null; 
    ByteArrayOutputStream byteStream = null; 
    FileOutputStream fileStream = null; 
    try 
    { 
     byteStream = new ByteArrayOutputStream(dataToCompress.length); 
     zipStream = new GZIPOutputStream(byteStream); 
     zipStream.write(dataToCompress); 

     compressedData = byteStream.toByteArray(); 

     fileStream = new FileOutputStream("C:/Users/UserName/Desktop/zip_file.gz"); 
     fileStream.write(compressedData); 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    finally 
    { 
     try{ zipStream.close(); } 
     catch(Exception e){ } 
     try{ byteStream.close(); } 
     catch(Exception e){ } 
     try{ fileStream.close(); } 
     catch(Exception e){ } 
    } 
    } 
} 
+3

「*以下代碼失敗*」不是有效的Java錯誤消息。 – 2013-02-08 17:13:30

+0

也請包括來自錯誤的堆棧跟蹤。 – 2013-02-08 17:15:19

+0

它只是生成一個不是ZIP文件的文件。沒有錯誤消息。 – 2013-02-08 17:17:24

回答

23

問題是您沒有關閉GZIPOutputStream。在關閉它之前,輸出將不完整。

你只需要在之前關閉它讀取字節數組。您需要重新訂購finally區塊才能實現此目的。

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

public class Zipper 
{ 
    public static void main(String[] args) 
    {  
    byte[] dataToCompress = "This is the test data." 
     .getBytes(StandardCharsets.ISO_8859_1); 

    try 
    { 
     ByteArrayOutputStream byteStream = 
     new ByteArrayOutputStream(dataToCompress.length); 
     try 
     { 
     GZIPOutputStream zipStream = 
      new GZIPOutputStream(byteStream); 
     try 
     { 
      zipStream.write(dataToCompress); 
     } 
     finally 
     { 
      zipStream.close(); 
     } 
     } 
     finally 
     { 
     byteStream.close(); 
     } 

     byte[] compressedData = byteStream.toByteArray(); 

     FileOutputStream fileStream = 
     new FileOutputStream("C:/Users/UserName/Desktop/zip_file.gz"); 
     try 
     { 
     fileStream.write(compressedData); 
     } 
     finally 
     { 
     try{ fileStream.close(); } 
      catch(Exception e){ /* We should probably delete the file now? */ } 
     } 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
    } 
} 

我不建議inititalizing流變量null,因爲這意味着你的finally塊也可以拋出一個NullPointerException

還要注意的是,你可以聲明mainIOException(那麼你就不需要最try聲明。)

有從zipStream.close();吞嚥異常的小點,因爲如果它拋出一個異常,你不會有一個有效的.gz文件(所以你不應該繼續寫它)。

另外,我不會吞下來自byteStream.close();的例外,但由於不同的原因 - 他們不應該被拋出(即在你的JRE和你有一個錯誤想知道這件事。)

+0

嗯,看來你回答我的問題。謝謝! – 2013-02-09 13:20:36

+1

我知道它已經很舊了,但是沒有明顯的原因,您在第二次嘗試時有zipStream = zipStream = {}。 – mangusbrother 2015-03-09 11:15:11

0

與此代碼嘗試..

try { 
    String inputFileName = "test.txt"; //may use your file_Path 
    String zipFileName = "compressed.zip"; 

    //Create input and output streams 
    FileInputStream inStream = new FileInputStream(inputFileName); 
    ZipOutputStream outStream = new ZipOutputStream(new FileOutputStream(zipFileName)); 

    // Add a zip entry to the output stream 
    outStream.putNextEntry(new ZipEntry(inputFileName)); 

    byte[] buffer = new byte[1024]; 
    int bytesRead; 

    //Each chunk of data read from the input stream 
    //is written to the output stream 
    while ((bytesRead = inStream.read(buffer)) > 0) { 
     outStream.write(buffer, 0, bytesRead); 
    } 

    //Close zip entry and file streams 
    outStream.closeEntry(); 

    outStream.close(); 
    inStream.close(); 

} catch (IOException ex) { 
    ex.printStackTrace(); 
} 

也可能是有幫助的這個..

+0

這個代碼直接寫入到一個ZIP文件;這是我不想要的。不過謝謝你。 – 2013-02-08 17:45:17

0

您可以使用下面的功能,它被測試並且工作正常。

一般而言,您的代碼有嚴重問題忽略的例外!返回nullcatch塊根本就沒有打印任何東西會使其很難調試

你不必寫ZIP輸出到一個文件,如果你想進一步處理它(如加密),你可以很容易地修改代碼以將輸出寫入內存中的流

public static String zip(File inFile, File zipFile) throws IOException {   
    FileInputStream fis = new FileInputStream(inFile); 
    FileOutputStream fos = new FileOutputStream(zipFile); 
    ZipOutputStream zout = new ZipOutputStream(fos); 

    try { 
     zout.putNextEntry(new ZipEntry(inFile.getName())); 
     byte[] buffer = new byte[BUFFER_SIZE]; 
     int len; 
     while ((len = fis.read(buffer)) > 0) { 
      zout.write(buffer, 0, len); 
     } 
     zout.closeEntry(); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
     return null; 
    } finally { 
     try{zout.close();}catch(Exception ex){ex.printStackTrace();} 
     try{fis.close();}catch(Exception ex){ex.printStackTrace();}   
    } 
    return zipFile.getAbsolutePath(); 
} 
+0

它可以添加這些'接近()'聲明在'嘗試/ catch'塊,並忽略錯誤 – iTech 2013-02-09 01:24:42

5

如果你還在尋找一個答案,你可以使用下面的代碼來獲取壓縮字節[]使用deflater和使用充氣解壓。

public static void main(String[] args) { 
     //Some string for testing 
     String sr = new String("fsdfesfsfdddddddsfdsfssdfdsfdsfdsfdsfdsdfggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggghghghghggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggfsdfesfsfdddddddsfdsfssdfdsfdsfdsfdsfdsdfggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggghghghghggggggggggggggggggggggggggggggggggggggggg"); 
     byte[] data = sr.getBytes(); 
     System.out.println("src size "+data.length); 
     try { 
      compress(data); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
    public static byte[] compress(byte[] data) throws IOException { 
     Deflater deflater = new Deflater(); 
     deflater.setInput(data); 
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length); 

     deflater.finish(); 
     byte[] buffer = new byte[1024]; 
     while (!deflater.finished()) { 
     int count = deflater.deflate(buffer); 
     outputStream.write(buffer, 0, count); 
     } 
     outputStream.close(); 
     byte[] output = outputStream.toByteArray(); 

     System.out.println("Original: " + data.length ); 
     System.out.println("Compressed: " + output.length); 
     return output; 
     } 
+0

謝謝你!這是我正在尋找的代碼:) – Freshchris 2015-02-23 13:44:20

0

要壓縮

private static byte[] compress(byte[] uncompressedData) { 
     ByteArrayOutputStream bos = null; 
     GZIPOutputStream gzipOS = null; 
     try { 
      bos = new ByteArrayOutputStream(uncompressedData.length); 
      gzipOS = new GZIPOutputStream(bos); 
      gzipOS.write(uncompressedData); 
      gzipOS.close(); 
      return bos.toByteArray(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     finally { 
      try { 
       assert gzipOS != null; 
       gzipOS.close(); 
       bos.close(); 
      } 
      catch (Exception ignored) { 
      } 
     } 
     return new byte[]{}; 
    } 

要解壓縮

private byte[] uncompress(byte[] compressedData) { 
     ByteArrayInputStream bis = null; 
     ByteArrayOutputStream bos = null; 
     GZIPInputStream gzipIS = null; 

     try { 
      bis = new ByteArrayInputStream(compressedData); 
      bos = new ByteArrayOutputStream(); 
      gzipIS = new GZIPInputStream(bis); 

      byte[] buffer = new byte[1024]; 
      int len; 
      while((len = gzipIS.read(buffer)) != -1){ 
       bos.write(buffer, 0, len); 
      } 
      return bos.toByteArray(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     finally { 
      try { 
       assert gzipIS != null; 
       gzipIS.close(); 
       bos.close(); 
       bis.close(); 
      } 
      catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     return new byte[]{}; 
    } 
3

我已經改善JITHINRAJ編碼 - 用來try-with-resources

private static byte[] gzipCompress(byte[] uncompressedData) { 
     byte[] result = new byte[]{}; 
     try (ByteArrayOutputStream bos = new ByteArrayOutputStream(uncompressedData.length); 
      GZIPOutputStream gzipOS = new GZIPOutputStream(bos)) { 
      gzipOS.write(uncompressedData); 
      gzipOS.close(); 
      result = bos.toByteArray(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return result; 
    } 

private static byte[] gzipUncompress(byte[] compressedData) { 
     byte[] result = new byte[]{}; 
     try (ByteArrayInputStream bis = new ByteArrayInputStream(compressedData); 
      ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
      GZIPInputStream gzipIS = new GZIPInputStream(bis)) { 
      byte[] buffer = new byte[1024]; 
      int len; 
      while ((len = gzipIS.read(buffer)) != -1) { 
       bos.write(buffer, 0, len); 
      } 
      result = bos.toByteArray(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return result; 
    }