c++ - 具有特定文件和特定缓冲区大小的 zlib Z_BUF_ERROR

标签 c++ zlib

我正在开发一些代码,需要能够解压缩大型 gzip 文件(未压缩的最大 5GB)并将它们读入内存。我宁愿对此保持清醒,而不是简单地将它们临时解压缩到磁盘,所以我一直在使用 zlib 来尝试实现这一点。我已经让它运行了,大部分时间。这意味着它运行我用作输入的 5 个文件中的 4 个。另一个文件在处理过程中给出了 Z_BUF_ERROR,我不想忽略它。

这最初发生在不同的代码中,但最终我将它一直带回到我从 zlib 网页上的 zpipe.c 获得的示例代码,无论我使用什么代码,它都会导致相同的 Z_BUF_ERROR 和只有这个文件。在阅读了关于 Z_BUF_ERROR 的几篇文章以及关于此的手册之后,我玩了很长时间代码。最终,我找到了一种方法,通过更改用于保存膨胀输出的缓冲区的大小来使其工作。通常在这一点上,我会称之为一天,直到它报告另一个文件的错误,但理想情况下,这将是某个时候的生产级代码,我想了解错误是什么,所以我可以防止它,而不仅仅是暂时修复它。特别是因为 gzip 能够很好地压缩和解压缩文件。

我尝试了以下变体:

  • 不同平台:CentOS、OSX
  • zlib 的不同版本:1.2.3、1.2.8(结果相同)
  • CHUNK 的值和输出的字节数(完整的是 783049330):
    • 2000000: 783049330
    • 1048576: 783049330
    • 1000000: 783049330
    • 100000: 783049330
    • 30000: 248421347
    • 25000: 31095404
    • 20000: 783049330
    • 19000: 155821787
    • 18000: 412613687
    • 17000: 55799133
    • 16384: 37541674
    • 16000: 783049330
  • 任何大于 4100000 的 CHUNK 大小都会出错
  • 尝试声明一个大于 CHUNK 的值(相同的结果)
  • 尝试使用 malloc 声明 out(相同结果)
  • 尝试使用 gzip 解压缩然后再次压缩文件,认为 gzip 元数据中可能存在某些问题(相同结果)
  • 尝试使用 gzip 压缩文件的单独未压缩版本以达到相同目的,但我相信原始 .gz 文件是从这个文件创建的(相同结果)

我可能已经尝试了这个列表之外的一些东西,因为我一直试图深入了解它一段时间,但只有更改 CHUNK 大小才能完成这项工作。我唯一担心的是,我不知道为什么不同的大小会起作用,而且我担心另一个 CHUNK 大小会使其他文件面临此问题的风险,因为同样,这只是一个文件的问题。

` 代码:

FILE* fp = fopen( argv[1], "rb" );
int ret = inf( fp, stdout );
fclose( fp );

int inf(FILE *source, FILE *dest)
{
  size_t CHUNK = 100000;
  int count = 0;
  int ret;
  unsigned have;
  z_stream strm;
  unsigned char in[CHUNK];
  unsigned char out[CHUNK];
  char out_str[CHUNK];

  /* allocate inflate state */
  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;
  strm.avail_in = 0;
  strm.next_in = Z_NULL;
  ret = inflateInit2(&strm, 16+MAX_WBITS);
  if (ret != Z_OK)
    return ret;
  /* decompress until deflate stream ends or end of file */
  do {
    strm.avail_in = fread(in, 1, CHUNK, source);
    if (ferror(source)) {
      (void)inflateEnd(&strm);
      return Z_ERRNO;
    }
    if (strm.avail_in == 0)
      break;
    strm.next_in = in;

    /* run inflate() on input until output buffer not full */
    do {
      strm.avail_out = CHUNK;
      strm.next_out = out;
      ret = inflate(&strm, Z_NO_FLUSH);
      switch (ret) {
        case Z_NEED_DICT:
          ret = Z_DATA_ERROR;     /* and fall through */
        case Z_DATA_ERROR:
        case Z_MEM_ERROR:
          (void)inflateEnd(&strm);
          return ret;
      }
      have = CHUNK - strm.avail_out;
      char out_str[have+1];
      strncpy( out_str, (char*)out, have );
      out_str[have] = '\0';

      // testing the ability to store the result in a string object and viewing the output
      std::cout << "out_str: " << std::string(out_str) << " ::" << std::endl;

      if( ret == Z_BUF_ERROR ){
        std::cout << "Z_BUF_ERROR!" << std::endl;
        exit(1);
      }
    } while (strm.avail_out == 0);

    /* done when inflate() says it's done */
  } while (ret != Z_STREAM_END);

  /* clean up and return */
  (void)inflateEnd(&strm);
  return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

`

最佳答案

你应该阅读评论where you got that code from . Z_BUF_ERROR 只是表明 inflate() 对该调用无能为力。只需继续并为下一个 inflate() 调用提供更多输入数据和更多输出空间。

关于c++ - 具有特定文件和特定缓冲区大小的 zlib Z_BUF_ERROR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26482218/

相关文章:

c++ - (c++) 无法迭代键哈希函数中的 vector

c++ - 从文件中读取会产生意外的输出

c++ - 在 C++ 中相互使用的两种类型

php - brew install zlib 在 osx mavericks 上抛出错误

c++ - Boost IO Stream 和 ZLib 提速

c# - 在 Python 中压缩 在 C# 中解压

c++ - 替代控制台输出流

windows - 如何在 Windows 上安装 Pillow 依赖项(没有二进制文件)?

javascript - 如何在 NodeJs 中下载和解压缩内存中的 zip 文件?

c++ - 高性能 'proper' C++ 替代变长数组