3

我有以下用于压缩和解压缩字符串的代码。

public static byte[] compress(String str)
{
    try
    {
        ByteArrayOutputStream obj = new ByteArrayOutputStream();
        GZIPOutputStream gzip = new GZIPOutputStream(obj);
        gzip.write(str.getBytes("UTF-8"));
        gzip.close();
        return obj.toByteArray();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    return null;
}

public static String decompress(byte[] bytes)
{
    try
    {
        GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes));
        BufferedReader bf = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
        StringBuilder outStr = new StringBuilder();
        String line;
        while ((line = bf.readLine()) != null)
        {
            outStr.append(line);
        }
        return outStr.toString();
    }
    catch (IOException e)
    {
        return e.getMessage();
    }
}

我在windows上压缩成字节数组,然后通过socket将字节数组发送到linux并在那里解压缩。然而,在解压缩时,似乎我所有的换行符都消失了。
所以我认为问题是linux到windows的关系。但是,我尝试在使用它的 Windows 上编写一个简单的程序,发现换行符仍然消失了。
任何人都可以阐明是什么原因造成的吗?我想不出任何解释。

4

2 回答 2

8

我认为问题出在这里:

while ((line = bf.readLine()) != null)
    {
        outStr.append(line);
    }

see 是换行符,readLine但不包含在返回值中line

问题可能比你想象的要严重。

readLine()获取所有字符,但不包括换行符(或各种回车符和换行符)或文件末尾。所以你不知道你得到的最后一行是否有换行符。

这可能无关紧要,如果是这样,您可以在另一个附加后添加:

outStr.append('\n');

某些文件可能会在文件末尾有一个额外的行结束。

如果它确实重要,您将需要使用read()然后输出您收到的所有字符。在这种情况下,您最终可能会遇到臭名昭著的“行尾是什么?” 您在 Windows、Linux 和 MacOS 之间提到的问题以及它们使用不同组合的返回和换行符来结束行的方式。

于 2013-10-10T15:49:43.927 回答
5

“吃掉”换行符的不是 GZIP。

就是这个代码:

    while ((line = bf.readLine()) != null)
    {
        outStr.append(line);
    }

readLine()方法读取一行(直到并包括一个行终止序列),然后在没有换行符的情况下返回它。然后,您将其附加到outStr...而不替换被剥离的行终止。

但是,即使您更换了线路终止,您也不能保证保留所使用的实际线路终止顺序......如果您这样做的话。

我建议您将readLine()电话替换为read()电话;即一次读取一个字符,然后缓冲数据。它一次解决了两个问题。它甚至可能更快,因为您避免了组装线字符串的不必要开销。

于 2013-10-10T15:51:47.927 回答