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();
}
}
}
我不建议将stream变量初始化为null
,因为这意味着您的代码finally
块也可以抛出NullPointerException
。
还要注意,您可以声明main
抛出IOException
(这样就不需要最外面的try
语句了。)
吞噬from中的异常没有什么意义zipStream.close();
,因为如果它引发异常,您将没有有效的.gz文件(因此,您不应继续编写它。)
另外,我不会byteStream.close();
因为其他原因而吞并异常-绝不应该抛出异常(即,您的JRE中存在错误,并且您想了解这一点。)