如何使用zlib创建一个与gz兼容的文件
How to create a gz-compatible file with zlib?
我想使用zlib用c++生成一个gz兼容的输出文件。
我安装了zlib的开发包,它可以用来在Unix和Windows上创建与gz兼容的文件。
sudo aptitude install libz-dev
虽然我写的是一个c++程序,但我认为在相关的地方我还是遵循了使用示例。我还将示例编译为zpipe.c
,未加更改。
唉,我得到的是不是一个gz兼容的输出。
$ ./zpipe.x < data.txt > x.gz
$ file x.gz
x.gz: data
$ gunzip x.gz
gzip: x.gz: not in gzip format
我认为这里的原因可能是,因为没有调用deflateSetHeader
。因此,我将其添加到我自己的源代码中,即(节选,您可以在这里找到完整的代码):
struct DeflateWrap { // RAII wrapper
z_stream strm_ ; // C-Struct from zlib.h
explicit DeflateWrap() : strm_{} {
strm_.zalloc = Z_NULL;
strm_.zfree = Z_NULL;
strm_.opaque = Z_NULL;
auto ret = deflateInit2(&strm_, LEVEL,
Z_DEFLATED, 15, 9, Z_DEFAULT_STRATEGY);
if(ret != Z_OK) throw std::runtime_error("Error ZLib-Init");
}
// ...more, eg. operator-> and *...
};
void pack(const string& infn) {
DeflateWrap dwrap {};
//...
dwrap->avail_in = indata.size();
dwrap->next_in = reinterpret_cast<unsigned char*>(indata.data());
gz_header header {0}; // <<< HEADER HERE
header.name = const_cast<unsigned char*>(
reinterpret_cast<const unsigned char*>(infn.c_str()));
header.comment = Z_NULL;
header.extra = Z_NULL;
bool first = true;
do {
dwrap->avail_out = outdata.size();
dwrap->next_out = reinterpret_cast<unsigned char*>(outdata.data());
if(first) {
cerr << deflateSetHeader(&(dwrap.strm_), &header); // <<< SET HDR HERE
first = false;
}
deflate(&(dwrap.strm_), Z_FINISH); // zlib.h: this packs
auto toWrite = outdata.size() - dwrap->avail_out;
outf.write(outdata.data(), toWrite);
} while (dwrap->avail_out == 0);
}
对于我的解释,我遵循deflateSetHeader
的手册:
- 我甚至用
deflateInit2
代替deflateInit
,可能没有必要 -
deflateSetHeader
的调用紧接deflateInit2
-
deflateSetHeader
的调用先于deflate
的调用
…我仍然从deflateSetHeader
调用中得到-2
,即Z_STREAM_ERROR
。虽然,我产生的输出可以用zpipe.c
解压缩,因此它不可能完全错误,可以吗?
任何想法如何设置一个gz兼容的标题?
更新:
正如我所看到的,我使用c++ -pendant来
SET_BINARY_MODE(stdin);
SET_BINARY_MODE(stdout);
:
ifstream inf{ infn, ifstream::binary };
ofstream outf { infn + ".gz", ofstream::binary };
另外,我想知道为什么我制作的zpipe.c
示例也没有像我之前描述的那样制作一个与zip兼容的文件。从我在这里读到的应该是
虽然我读了deflateSetHeader
的文档,输出文件是 gz兼容的,但再往下看,有一个提示,它可能不是这样的。
因此,当我使用不同的函数集该库支持读写gzip (.gz)格式的文件,使用类似于stdio的接口,使用以"gz"开头的函数。gzip格式与zlib格式不同。gzip是一个gzip包装器,在RFC 1952中有文档记录,封装在一个deflate流中。
gz...
时,我得到与gz兼容的输出和更简单的代码:
struct GzWrite { // RAII-Wrapper
gzFile gz_ ; // C-Struct aus zlib.h
explicit GzWrite(const string& filename)
: gz_{gzopen(filename.c_str(),"wb9")}
{
if(gz_==NULL) throw std::runtime_error(strerror(errno));
}
~GzWrite() {
gzclose(gz_);
}
int write(const char* data, size_t len) {
return gzwrite(gz_, data, len);
}
GzWrite(const GzWrite&) = delete; // keine Kopie
GzWrite& operator=(const GzWrite&) = delete; // keine Zuweisung
};
void packe(const string& infn) {
vector<char> indata = lese(infn); // lese Eingabe
GzWrite gz{infn+".gz"}; // initialisiere Ausgabe
auto res = gz.write(indata.data(), indata.size());
if(res==0) throw std::runtime_error("Fehler beim Schreiben");
}
windowsbits也可以是-8 ..-15为原始放气。在这种情况下,-windowBits决定窗口大小。然后Deflate()将生成原始的Deflate数据,不带zlib头或尾,并且不会计算adler32检查值。
对于可选的gzip编码,windowBits也可以大于15。将16添加到windowBits,以在压缩数据周围编写简单的gzip头和尾部,而不是zlib包装器。gzip头将没有文件名,没有额外的数据,没有注释,没有修改时间(设置为零),没有头crc,操作系统将设置为255(未知)。如果正在写入gzip流,则strm->adler是crc32而不是adler32。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 使用gzbuffer快速读取GZ的文件,然后按行划分内容
- C/C++:在不使用临时文件的情况下压缩(gz)数据
- 使用 boost::iostreams 和 zlib 读取.gz文件的运行时错误
- 什么是变更日志.Debian打包期间的Debian.gz文件
- 如何在不解压的情况下创建并附加到gz文件
- 试图将一个gz文件提供给一个c++程序
- 如何使用c++程序解压缩tar.gz文件?
- 在c++中读取压缩的gz文件(重文件)的有效方法
- 如何使用zlib创建一个与gz兼容的文件
- 在MATLAB中打开混合数据的.gz文件
- Boost::压缩文件夹tar.gz格式
- 使用 zlib 提取 gz 文件内容并保存
- C++/C 多个线程同时读取 gz 文件