文章目录
Poco库提供了压缩zip包和解压缩zip包的模块,通过该模块我们可以很方便的操作zip文件。在使用zip文件的压缩和解压缩功能的时候,我们需要先引入对应的模块库PocoZip。引入之后我们就可以自由的使用zip功能了,这里介绍一下zip模块的常规方法。
1.压缩单一文件
void compressSingleFile()
{
//指定输出zip文件
Poco::FileOutputStream out("test.zip");
//添加需要压缩的文件
Poco::Path theFile("testFile");
Compress c(out, true);
//添加测试文件
c.addFile(theFile, theFile.getFileName());
ZipArchive a(c.close());
}
2.压缩文件目录
void compressDirectory()
{
//指定输出文件名
Poco::FileOutputStream out("test.zip");
//递归创建目录
Poco::File aFile("some/");
if (aFile.exists()) aFile.remove(true);
Poco::File aDir("some/recursive/dir/");
aDir.createDirectories();
Poco::File aDir2("some/other/recursive/dir/");
aDir2.createDirectories();
Poco::File aF("some/recursive/dir/test.file");
aF.createFile();
//创建测试文件
Poco::FileOutputStream fos(aF.path());
fos << "just some test data";
fos.close();
//创建目录并递归添加
Poco::Path theFile(aFile.path());
theFile.makeDirectory();
Compress c(out, true);
c.addRecursive(theFile, ZipCommon::CL_MAXIMUM, false, theFile);
ZipArchive a(c.close());
Poco::File(aFile).remove(true);
}
3.操作压缩包中的文件
void addFileToZip()
{
//创建测试的压缩文件
Poco::FileOutputStream out("test.zip");
Poco::Path theFile("test.file");
Compress c(out, true);
c.addFile(theFile, theFile.getFileName());
ZipArchive a(c.close());
//重命名压缩包中的文件
ZipManipulator zm("test.zip", true);
zm.renameFile("test.file", "renametest.file");
//向压缩包中添加新文件
zm.addFile("doc/othertest.zip", "test.zip"));
ZipArchive archive=zm.commit();
//查找压缩包中的文件
assertTrue (archive.findHeader("doc/test.zipp") != archive.headerEnd());
//删除压缩包中的文件
zm.deleteFile("test.zip");
//替换压缩包中的文件
zm.replaceFile("test.zip", "doc.zip");
}
4.给压缩包添加注释
void SetZipComment()
{
std::string comment("Test Comment");
Poco::FileOutputStream out("comment.zip");
Poco::Path theFile("test.file");
Compress c(out, true);
c.addFile(theFile, theFile.getFileName());
//添加注释
c.setZipComment(comment);
ZipArchive a(c.close());
assertTrue (a.getZipComment() == comment);
}
5.使用zip64压缩(单个文件超过4G的时候)
参考的官方的例子
void createDataFile(const std::string& path, Poco::UInt64 size)
{
Poco::FileOutputStream out(path.c_str(), std::ios::trunc);
assertTrue ( ! out.fail() );
Poco::Buffer<char> buffer(MB);
for(int i = 0; size != 0; i++) {
std::memset(buffer.begin(), i, buffer.size());
Poco::UInt64 bytesToWrite = std::min(size, static_cast<Poco::UInt64>(buffer.size()));
out.write(buffer.begin(), bytesToWrite);
assertTrue ( ! out.fail() );
size -= bytesToWrite;
}
out.flush();
assertTrue ( ! out.fail() );
out.close();
assertTrue ( ! out.fail() );
}
void createZip64()
{
using FileMap = std::map<std::string, Poco::UInt64>;
std::cout << std::endl;
FileMap files;
files["data1.bin"] = static_cast<Poco::UInt64>(KB)*4096+1;
files["data2.bin"] = static_cast<Poco::UInt64>(KB)*16;
files["data3.bin"] = static_cast<Poco::UInt64>(KB)*4096-1;
for(FileMap::const_iterator it = files.begin(); it != files.end(); it++)
{
std::cout << '\t' << "createDataFile(" << it->first << ", " << it->second << ");" << std::endl;
createDataFile(it->first, it->second);
}
Poco::FileOutputStream out(Poco::Path::temp() + "zip64.zip", std::ios::trunc);
Compress c(out, true, true);
for(FileMap::const_iterator it = files.begin(); it != files.end(); it++)
{
const std::string& path = it->first;
std::cout << '\t' << "addFile(" << path << ");" << std::endl;
c.addFile(path, path, ZipCommon::CM_STORE);
}
ZipArchive a(c.close());
for(FileMap::const_iterator it = files.begin(); it != files.end(); it++)
{
const std::string& path = it->first;
Poco::UInt64 size = it->second;
ZipArchive::FileHeaders::const_iterator it2 = a.findHeader(path);
assertTrue (it2 != a.headerEnd());
const Poco::Zip::ZipLocalFileHeader& file = it2->second;
assertTrue (file.getUncompressedSize() == size);
assertTrue (file.getCompressedSize() == size);
}
for (FileMap::const_iterator it = files.begin(); it != files.end(); it++)
{
Poco::File(it->first).remove();
}
}
6.解压压缩包中的某个文件
void decompressSingleFile()
{
std::string testFile = "test.zip";
Poco::FileInputStream inp(testFile);
ZipArchive arch(inp);
ZipArchive::FileHeaders::const_iterator it = arch.findHeader("testfile.txt");
assertTrue (it != arch.headerEnd());
ZipInputStream zipin (inp, it->second);
std::ostringstream out(std::ios::binary);
Poco::StreamCopier::copyStream(zipin, out);
}
7.解压缩包中目录下的某个文件
void decompressSingleFileInDir()
{
std::string testFile = "test.zip";
Poco::FileInputStream inp(testFile);
ZipArchive arch(inp);
ZipArchive::FileHeaders::const_iterator it = arch.findHeader("testdir/testfile.txt");
assertTrue (it != arch.headerEnd());
ZipInputStream zipin (inp, it->second);
std::ostringstream out(std::ios::binary);
Poco::StreamCopier::copyStream(zipin, out);
assertTrue (!out.str().empty());
}
8.解压缩包中的全部文件
void UseZip::onDecompressError(const void* pSender, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string>& info)
{
++_errCnt;
}
void UseZip::decompress()
{
//指定压缩文件和输出目录
std::string testFile = "test.zip";
Poco::FileInputStream inp(testFile);
assertTrue (inp.good());
//@1压缩文件输入流
//@2输出目录
//@3输出模式false的时候递归创建文件目录
//true的时候把所有文件输出到一个目录中
Decompress dec(inp, Poco::Path::temp(),false);
//指定错误的回调函数
dec.EError += Poco::Delegate<UseZip, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string>>(this, &UseZip::onDecompressError);
//解压缩文件
dec.decompressAllFiles();
dec.EError -= Poco::Delegate<UseZip, std::pair<const Poco::Zip::ZipLocalFileHeader, const std::string>>(this, &UseZip::onDecompressError);
assertTrue (_errCnt == 0);
assertTrue (!dec.mapping().empty());
}
9.解压缩zip64文件
void verifyDataFile(const std::string& path, Poco::UInt64 size)
{
Poco::FileInputStream in(path);
assertTrue ( ! in.fail() );
Poco::Buffer<char> buffer1(MB);
Poco::Buffer<char> buffer2(MB);
for (int i = 0; size != 0; i++)
{
std::memset(buffer1.begin(), i, buffer1.size());
std::memset(buffer2.begin(), 0, buffer2.size());
Poco::UInt64 bytesToRead = std::min(size, static_cast<Poco::UInt64>(buffer2.size()));
in.read(buffer2.begin(), bytesToRead);
assertTrue (!in.fail() );
assertTrue (std::memcmp(buffer1.begin(), buffer2.begin(), static_cast<std::size_t>(bytesToRead)) == 0);
size -= bytesToRead;
}
char c;
in.read(&c, 1);
assertTrue ( in.eof() );
}
void decompressZip64()
{
std::map<std::string, Poco::UInt64> files;
files[Poco::Path::temp() + "data1.bin"] = static_cast<Poco::UInt64>(KB)*4096+1;
files[Poco::Path::temp() + "data2.bin"] = static_cast<Poco::UInt64>(KB)*16;
files[Poco::Path::temp() + "data3.bin"] = static_cast<Poco::UInt64>(KB)*4096-1;
for(std::map<std::string, Poco::UInt64>::const_iterator it = files.begin(); it != files.end(); it++)
{
Poco::File file(it->first);
if(file.exists())
file.remove();
}
Poco::FileInputStream in(Poco::Path::temp() + "zip64.zip");
Decompress c(in, Poco::Path::temp());
c.decompressAllFiles();
for(std::map<std::string, Poco::UInt64>::const_iterator it = files.begin(); it != files.end(); it++)
{
verifyDataFile(it->first, it->second);
}
}
10.校验压缩包中文件路径的合法性
ZipCommon::isValidPath(".");
ZipCommon::isValidPath("some/dir/or/another");
11.将压缩之后的某个文件解压出来
void CrcAndSizeAfterDataWithArchive()
{
std::string testFile = "data.zip";
Poco::FileInputStream inp(testFile);
assertTrue (inp.good());
Poco::Zip::ZipArchive zip(inp);
inp.clear();
inp.seekg(0);
Poco::Zip::ZipArchive::FileHeaders::const_iterator it = zip.headerBegin();
for ( ; it!=zip.headerEnd(); ++it)
{
Poco::Zip::ZipInputStream zipis(inp,it->second);
Poco::Path path(it->second.getFileName());
if (path.isFile())
{
Poco::FileOutputStream os(Poco::Path::temp() + "test.dat");
Poco::StreamCopier::copyStream(zipis,os);
}
}
}
12.获取压缩包的一些相关信息
void GetZipFileInfo()
{
std::string testFile = "test.zip";
Poco::FileInputStream inp(testFile);
assertTrue (inp.good());
//跳过某个文件
SkipCallback skip;
ZipLocalFileHeader hdr(inp, false, skip);
assertTrue (ZipCommon::HS_FAT == hdr.getHostSystem());
//获取版本号
int major = hdr.getMajorVersionNumber();
int POCO_UNUSED minor = hdr.getMinorVersionNumber();
assertTrue (major <= 2);
std::size_t hdrSize = hdr.getHeaderSize();
assertTrue (hdrSize > 30);
ZipCommon::CompressionMethod POCO_UNUSED cm = hdr.getCompressionMethod();
assertTrue (!hdr.isEncrypted());
Poco::DateTime aDate = hdr.lastModifiedAt();
Poco::UInt64 POCO_UNUSED cS = hdr.getCompressedSize();
Poco::UInt64 POCO_UNUSED uS = hdr.getUncompressedSize();
const std::string& POCO_UNUSED fileName = hdr.getFileName();
}