GZIP 压缩成字节数组 [英] GZIP compression to a byte array

查看:28
本文介绍了GZIP 压缩成字节数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to write a class that can compress data. The below code fails (no exception is thrown, but the target .gz file is empty.)
Besides: I don't want to generate the .gz file directly like it is done in all examples. I only want to get the compressed data, so that I can e.g. encrypt it before writting the data to a file.

如果我直接写入文件,一切正常:

If I write directly to a file everything works fine:

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 始终为空.

But, if I want to 'bypass' it to the byte array stream it does not produce a single byte - compressedData is always empty.

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.在您关闭它之前,输出将是不完整的.

The problem is that you are not closing the GZIPOutputStream. Until you close it the output will be incomplete.

您只需要在读取字节数组之前关闭它.您需要对 finally 块重新排序以实现此目的.

You just need to close it before reading the byte array. You need to reorder the finally blocks to achieve this.

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.

I do not recommend inititalizing the stream variables to null, because it means your finally block can also throw a NullPointerException.

另请注意,您可以声明 main 抛出 IOException(这样您就不需要最外面的 try 语句.)

Also note that you can declare main to throw IOException (then you would not need the outermost try statement.)

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

There is little point in swallowing exceptions from zipStream.close();, because if it throws an exception you will not have a valid .gz file (so you should not proceed to write it.)

此外,我不会吞下 byteStream.close(); 中的异常,但出于不同的原因 - 它们永远不应该被抛出(即,您的 JRE 中有一个错误,您想知道那个.)

Also I would not swallow exceptions from byteStream.close(); but for a different reason - they should never be thrown (i.e. there is a bug in your JRE and you would want to know about that.)

这篇关于GZIP 压缩成字节数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆