• 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());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    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");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    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);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    10.校验压缩包中文件路径的合法性

    ZipCommon::isValidPath(".");
    ZipCommon::isValidPath("some/dir/or/another");
    
    • 1
    • 2

    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);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    KMeans算法全面解析与应用案例
    asp.net web api2设置默认启动登录页面
    B+树的插入、删除和分裂,注意国内教材和国外的对于B+树的定义的不同
    国产ETL工具BeeDI 产品 之 全国连锁到集团总部 数据同步
    每日一题:什么是单点登录?如何实现?
    vue的双向数据绑定?动态给vue的data添加一个新的属性会发生什么?怎么解决?Object.defineProperty和proxy的对比?
    PD3.1详解 第二章(EPR)
    利用大语言模型(LLM )提高工作效率
    【LeetCode】面试题 17.19. 消失的两个数字
    怎么把本机设置成代理ip?
  • 原文地址:https://blog.csdn.net/yang1fei2/article/details/126650368