Java GZIP解压字符串和字节转换
我的代码有问题:Java GZIP解压字符串和字节转换,java,gzip,gzipoutputstream,Java,Gzip,Gzipoutputstream,我的代码有问题: private static String compress(String str) { String str1 = null; ByteArrayOutputStream bos = null; try { bos = new ByteArrayOutputStream(); BufferedOutputStream dest = null; byte b[] = str.getBytes();
private static String compress(String str)
{
String str1 = null;
ByteArrayOutputStream bos = null;
try
{
bos = new ByteArrayOutputStream();
BufferedOutputStream dest = null;
byte b[] = str.getBytes();
GZIPOutputStream gz = new GZIPOutputStream(bos,b.length);
gz.write(b,0,b.length);
bos.close();
gz.close();
}
catch(Exception e) {
System.out.println(e);
e.printStackTrace();
}
byte b1[] = bos.toByteArray();
return new String(b1);
}
private static String deCompress(String str)
{
String s1 = null;
try
{
byte b[] = str.getBytes();
InputStream bais = new ByteArrayInputStream(b);
GZIPInputStream gs = new GZIPInputStream(bais);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int numBytesRead = 0;
byte [] tempBytes = new byte[6000];
try
{
while ((numBytesRead = gs.read(tempBytes, 0, tempBytes.length)) != -1)
{
baos.write(tempBytes, 0, numBytesRead);
}
s1 = new String(baos.toByteArray());
s1= baos.toString();
}
catch(ZipException e)
{
e.printStackTrace();
}
}
catch(Exception e) {
e.printStackTrace();
}
return s1;
}
public String test() throws Exception
{
String str = "teststring";
String cmpr = compress(str);
String dcmpr = deCompress(cmpr);
}
此代码抛出java.io.IOException:未知格式(幻数ef1f)
事实证明,当转换字节新字符串(b1)
和字节b[]=str.getBytes()
字节时,字节被“损坏”。在行的输出处,我们已经有了更多的字节。如果您避免转换为字符串并使用字节处理行,那么一切都可以正常工作。对不起我的英语
我正在使用此函数解压缩服务器响应。谢谢您的帮助。您有两个问题:
- 您正在使用默认字符编码将原始字符串转换为字节。这将因平台而异。最好指定一种编码——UTF-8通常是个好主意
- 您试图通过调用
构造函数,将压缩结果的不透明二进制数据表示为字符串。该构造函数仅用于编码文本的数据。。。但这不是。对此,您应该使用base64。有一个简单的方法。(或者,根本不将压缩数据转换为文本-只返回一个字节数组。)字符串(byte[])
- 您几乎不应该捕获异常;捕获更具体的异常
- 你不应该只是抓住一个异常然后继续,就好像它从未发生过一样。如果您不能真正处理异常并且仍然成功地完成您的方法,那么您应该让异常在堆栈中冒泡(或者可能捕获它并将其包装为更适合您的抽象的异常类型)
当你压缩数据时,你总是得到二进制数据。此数据 无法转换为字符串,因为它不是有效的字符数据(在 任何编码)
科多是对的,非常感谢你给我的启发。我试图解压缩一个字符串(从二进制数据转换而来)。我修改的是在http连接返回的输入流上直接使用InflateInputStream。(我的应用程序正在检索大量的JSON字符串)这只是一个测试。事实上,从服务器上,我得到一个json字符串,它将是键“zip”。包含压缩数据的。我可以以字符串的形式获取键的内容。那么我需要提取这些信息。@AlexandrErofeev:所有这些都是你应该包含在问题中的信息。我怀疑JSON包含base64编码的数据。。。这就是我希望它能够表示二进制数据的方式。JSON不能直接包含二进制数据。因此,如果密钥是GZIP编码的,那么它可能也是Base64编码的,以将二进制数据转换为JSON可以包含的字符串。您可能应该添加一个JSON示例,其中包含问题的键。这是唯一的测试。@AlexandrErofeev:当有人在读你使用的编码时,它将不清楚。在我看来,最好明确地说出来。(如果只是测试,则完全删除所有异常处理,并让所有方法抛出
IOException
——这将简化代码。)
GZIPInputStream gs = new GZIPInputStream(bais);
public String unZip(String zipped) throws DataFormatException, IOException {
byte[] bytes = zipped.getBytes("WINDOWS-1251");
Inflater decompressed = new Inflater();
decompressed.setInput(bytes);
byte[] result = new byte[100];
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while (decompressed.inflate(result) != 0)
buffer.write(result);
decompressed.end();
return new String(buffer.toByteArray(), charset);
}