GZIP解压缩字符串和字节转换

Ale*_*eev 5 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();
        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);
}
Run Code Online (Sandbox Code Playgroud)

此代码抛出java.io.IOException:未知格式(幻数ef1f)

GZIPInputStream gs = new GZIPInputStream(bais);
Run Code Online (Sandbox Code Playgroud)

事实证明,当转换字节时new String (b1),byte b [] = str.getBytes ()字节被"破坏".在该行的输出处,我们已经有更多的字节.如果你避免转换为字符串并使用字节处理行 - 一切正常.对不起我的英语不好.


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);
}
Run Code Online (Sandbox Code Playgroud)

我用这个函数解压缩服务器响应.感谢帮助.

Jon*_*eet 8

你有两个问题:

  • 您正在使用默认字符编码将原始字符串转换为字节.这将因平台而异.指定编码更好 - UTF-8通常是个好主意.
  • 您只是通过调用String(byte[])构造函数来尝试将压缩结果的不透明二进制数据表示为字符串.该构造函数适用于编码文本的数据......但事实并非如此.您应该使用base64.有一个公共域base64库,这使这很容易.(或者,根本不要将压缩数据转换为文本 - 只返回一个字节数组.)

从根本上说,您需要了解不同的文本和二进制数据是什么 - 当您想要在两者之间进行转换时,您应该仔细阅读.如果要在字符串中表示"非文本"二进制数据(即不是编码文本的直接结果的字节),则应使用类似base64或hex的内容.如果要将字符串编码为二进制数据(例如,将某些文本写入磁盘),则应仔细考虑要使用的编码.如果另一个程序要读取你的数据,你需要计算出它所期望的编码 - 如果你自己完全控制它,我通常会选择UTF-8.

此外,代码中的异常处理很差:

  • 你几乎永远不会抓住Exception; 抓住更具体的例外
  • 你不应该只是抓住一个例外并继续,好像它从未发生过一样.如果您无法真正处理异常并仍然成功完成您的方法,您应该让异常冒泡到堆栈中(或者可能捕获它并将其包装在更适合的抽象异常类型中)