【问题标题】:GZIP eats newlinesGZIP 吃换行符
【发布时间】:2013-10-10 15:45:45
【问题描述】:

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

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 上编写一个简单的程序,发现换行符仍然消失了。
任何人都可以阐明是什么原因造成的吗?我想不出任何解释。

【问题讨论】:

    标签: java gzip gzipinputstream gzipoutputstream


    【解决方案1】:

    我认为问题出在这里:

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

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

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

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

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

    outStr.append('\n');
    

    某些文件可能会在文件末尾多出一行。

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

    【讨论】:

    • 你是对的。 read() 刚刚失败,但在我的情况下,.append("\n") 有效,如果我碰巧得到一个额外的换行符,我没问题,但到目前为止还没有发生。
    【解决方案2】:

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

    就是这个代码:

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

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

    但是,即使您更换了行终止符,您也不能保证保留所使用的实际行终止符序列……如果您这样做的话。

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

    【讨论】:

    • 非常抱歉,Lee 是第一个。此外,我尝试使用 read() ,不幸的是,由于不同的操作系统使用不同的字符,当我通过套接字将数据从一个传输到另一个时,换行符确实被吃掉了。不过感谢您的帮助 :) 解决方案是正确的,我真的很喜欢它。
    猜你喜欢
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    相关资源
    最近更新 更多