【发布时间】:2012-02-08 19:43:05
【问题描述】:
我一直在寻找一种在 C++ 中创建 zip 文件的良好、可移植的方法,但一直未能成功。我在不同的地方读到它可以使用 Boost IOstream 库,但我在参考中找不到任何源代码甚至文档:
http://www.boost.org/doc/libs/1_48_0/libs/iostreams/doc/index.html
有人有好的参考吗?我在谷歌上搜索了很多,但没有想出多少。
【问题讨论】:
我一直在寻找一种在 C++ 中创建 zip 文件的良好、可移植的方法,但一直未能成功。我在不同的地方读到它可以使用 Boost IOstream 库,但我在参考中找不到任何源代码甚至文档:
http://www.boost.org/doc/libs/1_48_0/libs/iostreams/doc/index.html
有人有好的参考吗?我在谷歌上搜索了很多,但没有想出多少。
【问题讨论】:
我不认为 boost::iostreams 可以打开 zip 文件。见Unziping a zip file with boost and Visual C++ 2005。
boost::iostreams 可用于使用 zlib、gzip 或 bzip2 压缩流或单个文件。您可以在这里找到一些示例:
但是,它无法读取 zip 文件中的目录信息。
另一方面,您需要使用第三方库:zlib 和 bzip2 来编译 boost。请参阅installation information。
【讨论】:
我编写了一个简单的 zip 文件生成器,允许与 iostreams 一起使用。 它包含在 partio 库中 https://github.com/wdas/partio/blob/master/src/lib/io/ZIP.h https://github.com/wdas/partio/blob/master/src/lib/io/ZIP.cpp
例如,您可以通过以下方式创建一个包含两个文件的 zip 文件
ZipFileWriter zip("foo.zip");
std::ostream* o = zip.Add_File("test.txt");
*o << "look a zip file" << std::endl;
delete o;
std::ostream* o2 = zip.Add_File("test2.txt");
*o2 << "look another file" << std::endl;
delete o2;
然后可以通过这样做来读取文件
ZipFileReader zip("foo.zip");
std::istream* i = zip.Get_File("test.txt");
std::string foo;
*i >> foo;
std::cout << foo << std::endl;
delete i;
【讨论】:
也许它不是一个 zip 文件,而是一个压缩文件,如果它可以帮助你的意图。 实际上,我对此进行了测试:
#include <fstream>
#include <sstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/zlib.hpp>
TEST(MyTests, SaveZipFile)
{
using namespace std;
ofstream file("a.z", ios_base::out | ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
out.push(boost::iostreams::zlib_compressor());
out.push(file);
stringstream sstr{"nihao"};
boost::iostreams::copy(sstr, out);
}
TEST(MyTests, OpenZipFile)
{
using namespace std;
ifstream file("a.z", ios_base::in | ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::zlib_decompressor());
in.push(file);
stringstream sstr;
boost::iostreams::copy(in, sstr);
cout << sstr.str() << endl;
ASSERT_EQ(sstr.str(), string("nihao"));
}
【讨论】:
这是无缝处理 zip 文件的有用流类!
但要注意文件 ZIP.cpp 中有一个小错误,请考虑:第 191 行。阅读
char* buf=new char[std::max(comment_length,std::max(filename_length,extra_length))];
istream.read(buf,filename_length);
buf[filename_length]=0;
这忽略了缓冲区需要一个更多字符空间用于终止符的事实(第 193 行),这可能会破坏堆!因此第 191 行应该是
char* buf=new char[std::max(comment_length,std::max(static_cast<unsigned short>(filename_length+1),extra_length))];
所以,如果你打算使用这个类,你应该考虑修复这个错误。没问题。
【讨论】: