【问题标题】:Encode string in Android so PHP would be able to gzdecompress it?在Android中编码字符串以便PHP能够gzdecompress它?
【发布时间】:2015-01-12 19:36:32
【问题描述】:

如何正确压缩字符串,以便 PHP 能够解压?

我试过这个:

public static byte[] compress(String string) throws IOException {
    ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
    DeflaterOutputStream gos = new DeflaterOutputStream(os);
    // ALSO TRIED GZOutputStream, same results!
    gos.write(string.getBytes());
    gos.close();
    byte[] compressed = os.toByteArray();
    os.close();
    return compressed;
}

但 PHP 无法将输出识别为有效的 GZip 压缩字符串...

问题似乎在于 Android 添加了一些页眉/页脚...

例如,当我通过 PHP 使用 gzcompress 压缩 something 单词时,我得到了与 Android 相似的结果,但不够相似,所以 PHP 可以读取它:

something(十六进制转储):

Android1f8b08000000000000002bcecf4d2dc9c8cc4b0700fb31da0909000000

PHP789c2bcecf4d2dc9c8cc4b0700134703cf

最奇怪的是,通过将GZOutputStream 更改为DeflaterOutputStream 它解决了something 字的问题,但问题仍然出现在更长的字符串...

附言。从 Android 生成的数据中删除标题 10 个字符根本没有帮助。


编辑:我尝试在 PHP 中解压缩它:

  • gzdecode() - 这个函数在标准的 Debian PHP5 中不存在 版本。
  • gzdecompress() - 不起作用

还有一些从 PHP 站点 cmets 模拟 gzdecode() 的函数,这些函数并没有真正做太多。

以上所有,删除前 10 个字节并保留它们。

PS2。我尝试了 Stack Overflow 和其他来源的每一个解决方案,但仍然没有。它不是重复的。


EDIT2 (BINARY DUMP):使用 Android 生成的示例数据无法通过来自 PHP.NET:data.compressedgzuncompress()pseudo-gzdecode() 函数解压缩。

解压后应该是一些JSON。

【问题讨论】:

  • 这里的 cmets 有点“发热”,所以我把它们移走了。如果你不能文明,就不要发帖。
  • 在所有 cmets 被立即删除后,我正在替换我的十六进制注释:您的十六进制转储缺少所有前导零。您需要每个字节打印两个十六进制数字,否则一串十六进制数字是不明确的。我编辑了您的问题以修复十六进制转储。
  • 啊好吧,我现在明白十六进制有什么问题了。咖啡的奇迹。我在EDIT2 中链接了二进制转储。
  • 您是否有可能手动压缩数据,然后通过默认自动压缩的方法将其发送到服务器,例如HttpURLConnection,还是类似的?
  • 双重压缩已经在我的回答中。自 EDIT2 提供实际数据后不久。

标签: php android gzip


【解决方案1】:

1f8b 开头的Android 数据是一个gzip 流。在 php 中,您为此使用 gzdecode()。 php 上的gzencode() 制作 gzip 流。

789c开头的php数据是一个zlib流。你使用gzcompress() 来制作它,你将使用gzuncompress() 来解码它。

这两个流中包含的压缩数据(以2bce 开头)是原始放气数据。你可以使用gzinflate() 来解码,如果你碰巧在某个地方做到了,你可以使用gzdeflate() 来生成原始的deflate。

只是吐槽一下,gzencode()gzcompress()gzdeflate() 是有史以来编造出来的一些最具误导性的函数名称,因为其中只有一个与 gzip 相关,但都以 gz 开头,并且没有任何内容名称gzcompress() 表示zlib。

更新:

“EDIT2”数据由于某种原因被双重压缩。它首先被压缩为 zlib 格式,然后该 zlib 流被压缩为 gzip 格式。 (虽然gzip不能压缩已经压缩过的数据,所以还是大了一点。)

您应该修复导致它被双重压缩的问题。或者,如果您无法控制,您可以对其进行双重解压缩,首先使用 RFC 1952 规范剥离 gzip 标头,然后对原始 deflate 数据使用 gzinflate(),然后对结果使用 gzdecompress()

【讨论】:

  • gzdecode() 函数在大多数 PHP(非 Windows)版本中不可用,您可能没有注意到,我不使用 GZOutputStream,而是使用 DeflaterOutputStream。无论如何......仍然没有解决方案。
  • 然后您可以使用 RFC 1952 中的信息手动解码 gzip 标头,然后在原始 deflate 数据上使用gzinflate()。 (仅删除前十个字节可能会或可能不会起作用,因为标头可能会超过十个字节,具体取决于内容。)
  • 如果你正在生成一个 zlib 流,那么 gzdecompress() 将处理它。如果您在使用较大的流时遇到问题,那么数据在途中的某个地方被其他错误破坏了。
  • 我并不粗鲁,只是累了...尝试了 100000 种不同解决方案的方法,但仍然一无所获...抱歉,如果您有这种感觉。 gzinflate() 不起作用,无论我是否删除前 10 个字节。数据没有损坏。我查过了。
  • 然后提供您无法解码的数据示例。 (正确转换为十六进制。)我预测要么a)数据可以被解码,要么b)它已损坏..
猜你喜欢
  • 2013-04-01
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-19
  • 2016-07-15
相关资源
最近更新 更多