Poco库使用:文件压缩和解压缩


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();
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农飞飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值