GZIP压缩为字节数组



我正在尝试编写一个可以压缩数据的类。以下代码失败(没有引发异常,但目标.gz文件为空。)
此外:我不想像所有示例中那样直接生成.gz文件。我只想压缩数据,这样我就可以在将数据写入文件之前对其进行加密。

如果我直接写入一个文件,一切都很好:

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

问题是您没有关闭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();
    }
  }
}

我不建议将流变量初始化为null,因为这意味着您的finally块也可以抛出NullPointerException

还要注意,您可以声明main来抛出IOException(这样就不需要最外层的try语句了。)

zipStream.close();中吞下异常没有什么意义,因为如果它抛出异常,您将没有有效的.gz文件(因此您不应该继续编写它)

此外,我不会接受byteStream.close();的异常,但原因不同——它们永远不应该被抛出(即JRE中有一个错误,您可能想知道这一点。)

我改进了JITHINRAJ的代码-使用资源进行尝试:

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);
            // You need to close it before using bos
            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;
    }

如果您仍在寻找答案,可以使用以下代码使用deflater获取压缩字节[],并使用inflater对其进行解压缩。

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

压缩

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[]{};
    }

大多数示例都有错误的异常处理。

public static byte[] gzipBytes(byte[] payload) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try (GZIPOutputStream gzip = new GZIPOutputStream(baos)) {
        gzip.write(payload);
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
    // note: toByteArray should be called after try-with-resources, not inside
    return baos.toByteArray();
}
public static byte[] gunzipBytes(byte[] gzPayload) {
    ByteArrayInputStream bais = new ByteArrayInputStream(gzPayload);
    try (GZIPInputStream gzip = new GZIPInputStream(bais)) {
        // java 9+ required for this method
        return gzip.readAllBytes();
    } catch (IOException e) {
        throw new UncheckedIOException("Error while unpacking gzip content", e);
    }
}

您可以使用下面的函数,它经过测试,运行良好。

一般来说,您的代码存在严重的忽略异常的问题!返回null或简单地不在catch块中打印任何内容将使调试变得非常困难

如果你想进一步处理(例如加密),你不必将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();
}

尝试使用此代码。。

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

这一次也可能有帮助。。

  • http://www.java-samples.com/java/zip_files_in_a_folder_using_java.htm

相关内容

  • 没有找到相关文章

最新更新