【问题标题】:Php's gzcompress in JavaJava 中 PHP 的 gzcompress
【发布时间】:2012-08-26 09:17:35
【问题描述】:

我尝试像 php 的 gzcompress 函数那样在 Java 中压缩字符串。但我无法在结果中得到相同的字节数组。

我的 php 代码:

<?php
echo 'This is a test';
$compressed = gzcompress('This is a test');
echo '<br>';
for ($i=0; $i<strlen($compressed); $i++) {
    echo '['.$i.'] = '.ord($compressed[$i]).'<br>';
}
?>

结果:

这是一个测试

[0] = 120 
[1] = 156 
[2] = 11 
[3] = 201 
[4] = 200 
[5] = 44 
[6] = 86 
[7] = 0 
[8] = 162 
[9] = 68 
[10] = 133 
[11] = 146 
[12] = 212 
[13] = 226 
[14] = 18 
[15] = 0 
[16] = 36 
[17] = 115 
[18] = 4 
[19] = 246 

Java 代码:

public class Main {

    public static byte[] compressString(String uncompressedString) throws IllegalArgumentException, IllegalStateException {
        try {
            byte[] utfEncodedBytes = uncompressedString.getBytes();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos)) {
                gzipOutputStream.write(utfEncodedBytes);
                gzipOutputStream.finish();
            }
            return baos.toByteArray();
        } catch (Exception e) {
            throw new IllegalStateException("GZIP compression failed: " + e, e);
        }
    }

    public static void main(String[] args) {
        String input = "This is a test";
        System.out.println("Input:  " + input);
        byte[] compressed = compressString(input);
        for (int i = 0; i < compressed.length; i++) {
            System.out.println("[" + i + "] = " + (compressed[i] & 0xFF));
        }
    }
}

结果:

输入:这是一个测试

[0] = 31 
[1] = 139 
[2] = 8 
[3] = 0 
[4] = 0 
[5] = 0 
[6] = 0 
[7] = 0 
[8] = 0 
[9] = 0 
[10] = 11 
[11] = 201 
[12] = 200 
[13] = 44 
[14] = 86 
[15] = 0 
[16] = 162 
[17] = 68 
[18] = 133 
[19] = 146 
[20] = 212 
[21] = 226 
[22] = 18 
[23] = 0 
[24] = 50 
[25] = 159 
[26] = 122 
[27] = 192 
[28] = 14
[29] = 0 
[30] = 0 
[31] = 0 

压缩数组的中间部分是一样的。但它们的开始和结束是不同的。

【问题讨论】:

  • 它适用于 java.util.zip.Deflater。我在 php 中得到与 gzcompress 相同的结果。我还将字符集更改为 windows-1252,因为我遇到了俄语字符问题。

标签: java php compression gzip


【解决方案1】:

documentation for the gzcompress function具体说明它使用的压缩算法是zlib,也就是

与 gzip 压缩不同,后者包含一些标头数据。 gzip 压缩见 gzencode()。

Java 的 GZIPOutputStream 进行正确的 gzip 压缩,包括正确的标头。 DeflaterOutputStream 在没有 gzip 标头的情况下进行简单的放气,这可能更接近您所追求的,或者有第三方解决方案,例如 JZlib

【讨论】:

    【解决方案2】:

    根据 RFC http://www.gzip.org/zlib/rfc-gzip.html

    它声明文件的开头应该包含。

    ID1(标识 1) ID2(标识 2) 它们具有固定值 ID1 = 31 (0x1f, \037), ID2 = 139 (0x8b, \213),以将文件识别为 gzip 格式。

    CM(压缩方法) 这标识了文件中使用的压缩方法。 CM = 0-7 保留。 CM = 8 表示“deflate”压缩方法,这是 gzip 常用的一种,在其他地方有文档说明。

    所以前三个字节应该是 31、139、8。第四个字节应该是 0-31 之间的值(使用位 0 到 4,并且保留 5,6 和 7)。我怀疑你在 PHP 中看到的输出不是 gz 格式。

    【讨论】:

    • 感谢您的快速回答。在您的帮助下,我了解到 java 代码适用于 RFC 1952。但是 php 的 gzcompress 适用于 RFC 1950(ZLIB 压缩数据格式规范版本 3.3 tools.ietf.org/html/rfc1950)。但我仍然不明白如何在 Java 中使用 ZLIB 压缩。
    • @user1625608 我认为标准 JRE 库中没有内置任何东西可以执行 zlib,但是您可以使用第三方库(请参阅我的更新答案)。
    • 也许 DeflatorOutputStream 和 inflatorInputStream 会这样做。它就像没有页眉和页脚的 GZ。鉴于 GZip 的标准,有理由不使用它吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多