【问题标题】:Moving compressed strings between C++ and PHP with zlib使用 zlib 在 C++ 和 PHP 之间移动压缩字符串
【发布时间】:2010-10-28 18:54:51
【问题描述】:

我正在处理一个项目,其中运行 PHP 的 Windows Web 服务器通过非常慢的连接与运行用 C++ 编写的应用程序的后端 Linux 服务器进行通信。因为两台机器之间的连接太慢了,我想压缩它们之间的流量。

我已经到了可以压缩字符串、将其保存到文件、读取文件以及使用 Zlib 在 C++ 中解压缩字符串的地方,在 PHP 中也是如此。但是,如果我尝试用一​​种语言压缩一个字符串并用另一种语言解压缩它(就像在现实世界中发生的那样),我会收到错误,抱怨压缩数据已损坏。我还注意到在 C++ 中压缩的相同字符串会生成与 PHP 不同的文件,这让我相信 Zlib 在每种语言上使用不同的压缩算法。

我在两边都使用默认设置。我用来做压缩和解压的 C++ 是

compress((Bytef*)compressed, (uLongf*)&compressedLength, (Bytef*)uncompressed, (uLong)uncomressedLength);
uncompress((Bytef*)uncompressed, (uLongf*)&uncomressedLength, (Bytef*)compressed, (uLong)compressedLength);

而 PHP 代码是

$compressed = gzcompress($uncompressed);
$uncompressed = gzuncompress($compressed);

为什么这些会导致不同的压缩字符串?这是导致减压问题的原因吗?我应该怎么做才能让它工作?另外,我不致力于 Zlib。 Zlib 是我最初的研究发现的,但如果有更好的方法来做到这一点,我会全力以赴。

编辑:实际上,在进行了更多测试之后,C++ 似乎正在处理我最初的测试用例,但并非普遍适用。我用输入“hellohellohello”尝试了它,在解压缩时,它报告了一个 Z_DATA_ERROR 并将其解压缩为“hello”。我想这意味着我在 C++ 方面做错了,这也许可以解释为什么 PHP 不满意解压缩 C++ 压缩字符串。

编辑 2:我试用了 zpipe.c 示例程序,它可以正确解压缩 PHP 压缩的字符串,并生成 PHP 可以解压缩的压缩字符串。显然,我的 C++ 代码中存在问题。我对 compress 和 uncompress 的使用不正确,或者我正在错误地读取和写入文件。压缩或解压缩程序都不能与 zpipe 正确交互。

更新:我现在可以使用 PHP 压缩字符串并使用 PHP 或 C++ 读取它,我可以使用 C++ 压缩字符串并使用 C++ 读取它,但是尝试使用 PHP 读取它会导致 PHP 警告:gzuncompress():数据错误。有什么不同会导致这种工作/不工作场景的组合?

【问题讨论】:

  • 这不是您用于(解)压缩的 C++,这只是函数声明。
  • 它们是库调用。 compressed、compressedLength 等是我正在使用的变量的实际名称,并且由于 Zlib 使用它自己的类型而不是标准类型,所以我在调用时会转换它们。
  • 您能发布您完全更新的代码吗?谢谢。

标签: php c++ compression zlib


【解决方案1】:

Zlib 的默认压缩级别为 6 - 您可以尝试将其作为第二个参数传递给 gzcompress for PHP

string gzcompress ( string $data [, int $level = -1 ] )

来自ZLIB manual

压缩级别必须是 Z_DEFAULT_COMPRESSION,或介于 0 之间 和 9:1 给出最佳速度,9 给出 最佳压缩,0 表示没有 完全压缩(输入数据是 一次只复制一个块)。 Z_DEFAULT_COMPRESSION 请求一个 速度和之间的默认折衷 压缩(目前相当于 6级)

【讨论】:

  • 您可能还想确保其他设置以及库版本相同或兼容。
  • 更改压缩级别似乎对 PHP 端没有影响。无论我设置的级别如何,它都有效。如果我改变压缩级别,C++ 端的不正确解压缩是不同的,但至少对于 0、6 和 9,它总是错误的。
  • 很奇怪。我必须让 ZLIB 与 C++、C# 和 Java 一起工作,尽管文件不同,但解压缩总是有效的。是否有一些流或文件刷新操作您没有在任一端执行?
  • 当我使用 PHP 压缩时,脚本的最后一行是一个 fclose,它应该将流刷新到文件中。我正在使用 fread(compressed, sizeof(compressed), 1, in); 在 C++ 端读取它,并且压缩比文件的大小大很多倍,所以它应该读取整个内容。在双方的 fopen 中,我在模式字符串中使用 b 来表示它是一个二进制文件,但它的使用(或缺少它)似乎没有什么区别。
  • 您可以尝试在 C++ 端进行压缩/解压缩,在 PHP 端进行同样的操作,以排除两端的写入器/读取器问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
相关资源
最近更新 更多