【问题标题】:zlib gzwrite not writing entire file Czlib gzwrite 不写整个文件 C
【发布时间】:2020-05-02 00:52:36
【问题描述】:

我目前正在尝试通过 C 中的套接字将 .tar.gz 文件从服务器传输到客户端,但我遇到了一个错误,即使用 gzopen + gzread 从 tar.gz 读取并将其写入使用 gzwrite 的新 tar.gz 文件失败会导致 tar.gz 文件损坏,甚至与原始文件大小不同。

起初我认为这与我的套接字逻辑有关,但我在较小的范围内对其进行了测试,只是读取并立即将其写入同一目录,即使这样错误仍然存​​在。以下是一些演示该问题的示例代码:

gzFile gz = gzopen("tar.tar.gz", "r");
// tar.tar contains one text file, tarred with "tar -cvf tar.tar text.txt"
// tar.tar.gz created with "gzip tar.tar"
struct stat st;
stat("tar.tar.gz", &st);  // get size
unsigned int gz_buffer_size = st.st_size;
printf(".gz size: %d\n", gz_buffer_size);
unsigned char *gz_buffer = malloc(gz_buffer_size);
gzread(gz, buffer, buffer_size);
gzclose(gz);

gzFile test = gzopen("test.tar.gz", "w");
printf("wrote to test: %d\n", gzwrite(test, gz_buffer, gz_buffer_size));
gzclose(test);

运行上述程序后,程序会向 stdout 打印我的 .gz 的大小为 169 字节,甚至 gzwrite 也会打印出它向新的 .gz 文件写入了 169 字节。那么为什么当我跑的时候 stat -c %s test.tar.gz我知道test.tar.gz的大小是24?

【问题讨论】:

  • 看来您正在使用buffer_size 读取buffer,然后使用gz_buffer_size 写入gz_buffer
  • 你为什么要解压缩然后重新压缩文件而不是按原样发送??
  • 只是为了演示 gzwrite 错误;令人尴尬的是,我没有发现我使用缓冲区和缓冲区大小而不是 gz_buffer 和 gz_buffer_size 的情况。谢谢。

标签: c linux zlib


【解决方案1】:

这里有几件事:

  • 您正在统计一个 压缩 文件以获取其大小,并从中读取一些 未压缩 字节。您没有提供buffer_size 的任何定义或初始化,但您可能没有阅读整个文件,只是其中的一部分。

  • 您完全忽略了gzread() 的返回值,因此您不知道实际读取了多少字节。

  • 您正在读取 buffer 并写入未初始化的 gz_buffer

  • 然后您将压缩该未初始化的内存并将其写入另一个文件。 gzwrite() 返回压缩的字节数,而不是压缩片段的长度(由于块、填充等取决于未来的写入(如果有的话),它无法知道)。 169 个未压缩字节下降到 24 个压缩字节并非不合理。

  • 您没有进行任何错误检查;在对返回/设置的内容执行任何操作之前,您的所有函数都应进行检查以确保它们成功。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    相关资源
    最近更新 更多