使用c++解压rar文件,基于UnRAR64,非命令行

最近项目需要解压缩rar文件,我们都知道rar是闭源收费软件,如果直接采用命令行可能会有限制,或者盗版问题,使用正版的winrar命令行解压rar文件是否有限制,这个我没来得及测试,但是从交互体验上来说,命令行对于很多情况的处理也不太友好,比如是否出错,比如异常处理,甚至某些高级功能,比如自定义解压缩的文件名等等,这些在命令行中不太好实现甚至无法实现。

网上很多关于c++解压rar的代码都是基于命令行的,这不是我想要的。

我想找能够解压rar的库或者dll,经过一番寻找,发现rarlab官网已经提供了UnRAR64,可以直接下载运行,这里提供一下下载地址:https://www.rarlab.com/rar/unrardll-624.exeicon-default.png?t=N7T8https://www.rarlab.com/rar/unrardll-624.exe

其他版本在这个页面:WinRAR archiver, a powerful tool to process RAR and ZIP filesicon-default.png?t=N7T8https://www.rarlab.com/rar_add.htm

使用官方的例子,即可实现winrar的解压缩,不过为了方便使用,我拓展了一下官方的代码,可以实现列出文件和解压缩rar文件到指定的目录,修改比较简单,这里直接上代码:

#pragma once#include <windows.h>
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
#include <vector>#include "unrar.h"enum { EXTRACT, TEST, PRINT, LIST };int CommandLine(int Argc, char *Argv[]);void ExtractArchive(char *ArcName,int Mode);
void ExtractArchive(char *ArcName, char* DstDir);
void ListArchive(char *ArcName);
size_t ListArchive(char *ArcName, std::vector<std::string>& vFiles);
void ShowComment(wchar_t *CmtBuf);
void OutHelp(void);enum ERR_TYPE {ERR_OPEN, ERR_READ, ERR_PROCESS};
void OutError(int Error,char *ArcName,int ErrType);void ShowArcInfo(unsigned int Flags,char *ArcName);
void PrintTime(const char *Label,unsigned int Low,unsigned int High);
void OutProcessFileError(int Error);
int CALLBACK CallbackProc(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);

实现文件:

#define STRICT#include "UnRDLL.h"int CommandLine(int Argc, char *Argv[])
{setlocale(LC_ALL, NULL);if (Argc!=3){OutHelp();return(0);}switch(toupper(Argv[1][0])){case 'X':ExtractArchive(Argv[2],EXTRACT);break;case 'T':ExtractArchive(Argv[2],TEST);break;case 'P':ExtractArchive(Argv[2],PRINT);break;case 'L':ListArchive(Argv[2]);break;default:OutHelp();return(0);}return(0);
}void ExtractArchive(char *ArcName,int Mode)
{HANDLE hArcData;int RHCode,PFCode;wchar_t CmtBuf[16384];struct RARHeaderData HeaderData;struct RAROpenArchiveDataEx OpenArchiveData;memset(&HeaderData,0,sizeof(HeaderData));memset(&OpenArchiveData,0,sizeof(OpenArchiveData));OpenArchiveData.ArcName=ArcName;OpenArchiveData.CmtBufW=CmtBuf;OpenArchiveData.CmtBufSize=sizeof(CmtBuf)/sizeof(CmtBuf[0]);OpenArchiveData.OpenMode=RAR_OM_EXTRACT;OpenArchiveData.Callback=CallbackProc;OpenArchiveData.UserData=Mode;hArcData=RAROpenArchiveEx(&OpenArchiveData);if (OpenArchiveData.OpenResult!=0){OutError(OpenArchiveData.OpenResult,ArcName,ERR_OPEN);return;}ShowArcInfo(OpenArchiveData.Flags,ArcName);if (OpenArchiveData.CmtState==1)ShowComment(CmtBuf);while ((RHCode=RARReadHeader(hArcData,&HeaderData))==0){switch(Mode){case EXTRACT:printf("\nExtracting %-45s",HeaderData.FileName);break;case TEST:printf("\nTesting %-45s",HeaderData.FileName);break;case PRINT:printf("\nPrinting %-45s\n",HeaderData.FileName);break;}PFCode=RARProcessFile(hArcData,(Mode==EXTRACT) ? RAR_EXTRACT:RAR_TEST,NULL,NULL);if (PFCode==0)printf(" OK");else{OutError(PFCode,ArcName,ERR_PROCESS);break;}}OutError(RHCode,ArcName,ERR_READ);RARCloseArchive(hArcData);
}void ExtractArchive(char *ArcName, char* DstDir)
{HANDLE hArcData;int RHCode,PFCode;wchar_t CmtBuf[16384];struct RARHeaderData HeaderData;struct RAROpenArchiveDataEx OpenArchiveData;memset(&HeaderData,0,sizeof(HeaderData));memset(&OpenArchiveData,0,sizeof(OpenArchiveData));OpenArchiveData.ArcName=ArcName;OpenArchiveData.CmtBufW=CmtBuf;OpenArchiveData.CmtBufSize=sizeof(CmtBuf)/sizeof(CmtBuf[0]);OpenArchiveData.OpenMode=RAR_OM_EXTRACT;OpenArchiveData.Callback=CallbackProc;OpenArchiveData.UserData= EXTRACT;hArcData=RAROpenArchiveEx(&OpenArchiveData);if (OpenArchiveData.OpenResult!=0){OutError(OpenArchiveData.OpenResult,ArcName,ERR_OPEN);return;}ShowArcInfo(OpenArchiveData.Flags,ArcName);if (OpenArchiveData.CmtState==1)ShowComment(CmtBuf);while ((RHCode=RARReadHeader(hArcData,&HeaderData))==0){printf("\nExtracting %-45s",HeaderData.FileName);PFCode=RARProcessFile(hArcData,RAR_EXTRACT,DstDir,NULL);if (PFCode==0)printf(" OK");else{OutError(PFCode,ArcName,ERR_PROCESS);break;}}OutError(RHCode,ArcName,ERR_READ);RARCloseArchive(hArcData);
}size_t ListArchive(char *ArcName, std::vector<std::string>& vFiles)
{HANDLE hArcData;int RHCode,PFCode;wchar_t CmtBuf[16384];struct RARHeaderDataEx HeaderData;struct RAROpenArchiveDataEx OpenArchiveData;wchar_t RedirName[1024];memset(&HeaderData,0,sizeof(HeaderData));memset(&OpenArchiveData,0,sizeof(OpenArchiveData));OpenArchiveData.ArcName=ArcName;OpenArchiveData.CmtBufW=CmtBuf;OpenArchiveData.CmtBufSize=sizeof(CmtBuf)/sizeof(CmtBuf[0]);OpenArchiveData.OpenMode=RAR_OM_LIST;OpenArchiveData.Callback=CallbackProc;OpenArchiveData.UserData=LIST;hArcData=RAROpenArchiveEx(&OpenArchiveData);if (OpenArchiveData.OpenResult!=0){OutError(OpenArchiveData.OpenResult,ArcName,ERR_OPEN);return 0;}ShowArcInfo(OpenArchiveData.Flags,ArcName);if (OpenArchiveData.CmtState==1)ShowComment(CmtBuf);HeaderData.RedirName=RedirName;HeaderData.RedirNameSize=sizeof(RedirName)/sizeof(RedirName[0]);while ((RHCode=RARReadHeaderEx(hArcData,&HeaderData))==0){__int64 UnpSize=HeaderData.UnpSize+(((__int64)HeaderData.UnpSizeHigh)<<32);__int64 PackSize=HeaderData.PackSize+(((__int64)HeaderData.PackSizeHigh)<<32);printf("\nName:   %s",HeaderData.FileName);vFiles.push_back(HeaderData.FileName);printf("\nSize:   %lld ",UnpSize);printf("\nPacked: %lld ",PackSize);PrintTime("mtime",HeaderData.MtimeLow,HeaderData.MtimeHigh);PrintTime("ctime",HeaderData.CtimeLow,HeaderData.CtimeHigh);PrintTime("atime",HeaderData.AtimeLow,HeaderData.AtimeHigh);if (HeaderData.RedirType!=0)printf("\n\tlink type %d, target %ls",HeaderData.RedirType,HeaderData.RedirName);if ((PFCode=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL))!=0){OutError(PFCode,ArcName,ERR_PROCESS);break;}printf("\n");}OutError(RHCode,ArcName,ERR_READ);RARCloseArchive(hArcData);return vFiles.size();
}void ListArchive(char *ArcName)
{HANDLE hArcData;int RHCode,PFCode;wchar_t CmtBuf[16384];struct RARHeaderDataEx HeaderData;struct RAROpenArchiveDataEx OpenArchiveData;wchar_t RedirName[1024];memset(&HeaderData,0,sizeof(HeaderData));memset(&OpenArchiveData,0,sizeof(OpenArchiveData));OpenArchiveData.ArcName=ArcName;OpenArchiveData.CmtBufW=CmtBuf;OpenArchiveData.CmtBufSize=sizeof(CmtBuf)/sizeof(CmtBuf[0]);OpenArchiveData.OpenMode=RAR_OM_LIST;OpenArchiveData.Callback=CallbackProc;OpenArchiveData.UserData=LIST;hArcData=RAROpenArchiveEx(&OpenArchiveData);if (OpenArchiveData.OpenResult!=0){OutError(OpenArchiveData.OpenResult,ArcName,ERR_OPEN);return;}ShowArcInfo(OpenArchiveData.Flags,ArcName);if (OpenArchiveData.CmtState==1)ShowComment(CmtBuf);HeaderData.RedirName=RedirName;HeaderData.RedirNameSize=sizeof(RedirName)/sizeof(RedirName[0]);while ((RHCode=RARReadHeaderEx(hArcData,&HeaderData))==0){__int64 UnpSize=HeaderData.UnpSize+(((__int64)HeaderData.UnpSizeHigh)<<32);__int64 PackSize=HeaderData.PackSize+(((__int64)HeaderData.PackSizeHigh)<<32);printf("\nName:   %s",HeaderData.FileName);printf("\nSize:   %lld ",UnpSize);printf("\nPacked: %lld ",PackSize);PrintTime("mtime",HeaderData.MtimeLow,HeaderData.MtimeHigh);PrintTime("ctime",HeaderData.CtimeLow,HeaderData.CtimeHigh);PrintTime("atime",HeaderData.AtimeLow,HeaderData.AtimeHigh);if (HeaderData.RedirType!=0)printf("\n\tlink type %d, target %ls",HeaderData.RedirType,HeaderData.RedirName);if ((PFCode=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL))!=0){OutError(PFCode,ArcName,ERR_PROCESS);break;}printf("\n");}OutError(RHCode,ArcName,ERR_READ);RARCloseArchive(hArcData);
}void ShowComment(wchar_t *CmtBuf)
{printf("\nComment:\n%ls\n",CmtBuf);
}void OutHelp(void)
{printf("\nUNRDLL.   This is a simple example of UNRAR.DLL usage\n");printf("\nSyntax:\n");printf("\nUNRDLL X <Archive>     extract archive contents");printf("\nUNRDLL T <Archive>     test archive contents");printf("\nUNRDLL P <Archive>     print archive contents to stdout");printf("\nUNRDLL L <Archive>     view archive contents\n");
}void OutError(int Error,char *ArcName,int ErrType)
{switch(Error){case ERAR_NO_MEMORY:printf("\nNot enough memory");break;case ERAR_BAD_DATA:printf("\n%s: archive header or data are damaged",ArcName);break;case ERAR_BAD_ARCHIVE:printf("\n%s is not RAR archive",ArcName);break;case ERAR_UNKNOWN_FORMAT:printf("Unknown archive format");break;case ERAR_EOPEN:if (ErrType==ERR_PROCESS) // Returned by RARProcessFile.printf("Volume open error");elseprintf("\nCannot open %s",ArcName);break;case ERAR_ECREATE:printf("File create error");break;case ERAR_ECLOSE:printf("File close error");break;case ERAR_EREAD:printf("Read error");break;case ERAR_EWRITE:printf("Write error");break;case ERAR_SMALL_BUF:printf("Buffer for archive comment is too small, comment truncated");break;case ERAR_UNKNOWN:printf("Unknown error");break;case ERAR_MISSING_PASSWORD:printf("Password for encrypted file or header is not specified");break;case ERAR_EREFERENCE:printf("Cannot open file source for reference record");break;case ERAR_BAD_PASSWORD:printf("Wrong password is specified");break;}
}void ShowArcInfo(unsigned int Flags,char *ArcName)
{printf("\nArchive %s\n",ArcName);printf("\nVolume:\t\t%s",(Flags & 1) ? "yes":"no");printf("\nComment:\t%s",(Flags & 2) ? "yes":"no");printf("\nLocked:\t\t%s",(Flags & 4) ? "yes":"no");printf("\nSolid:\t\t%s",(Flags & 8) ? "yes":"no");printf("\nNew naming:\t%s",(Flags & 16) ? "yes":"no");printf("\nRecovery:\t%s",(Flags & 64) ? "yes":"no");printf("\nEncr.headers:\t%s",(Flags & 128) ? "yes":"no");printf("\nFirst volume:\t%s",(Flags & 256) ? "yes":"no or older than 3.0");printf("\n---------------------------\n");
}void PrintTime(const char *Label,unsigned int Low,unsigned int High)
{if (Low!=0 || High!=0){FILETIME ft;ft.dwLowDateTime=Low;ft.dwHighDateTime=High;SYSTEMTIME ust,st;FileTimeToSystemTime(&ft,&ust);SystemTimeToTzSpecificLocalTime(NULL,&ust,&st);printf("\n%s:  %u-%02u-%02u %02u:%02u:%02u,%03u",Label,st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);}
}int CALLBACK CallbackProc(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2)
{switch(msg){case UCM_CHANGEVOLUMEW:if (P2==RAR_VOL_ASK){printf("\n\nVolume %S is required\nPossible options:\n",(wchar_t *)P1);printf("\nEnter - try again");printf("\n'R'   - specify a new volume name");printf("\n'Q'   - quit");printf("\nEnter your choice: ");switch(toupper(getchar())){case 'Q':return(-1);case 'R':{wchar_t *eol;printf("\nEnter new name: ");fflush(stdin);// fgetws may fail to read non-English characters from stdin// in some compilers. In this case use something more// appropriate for Unicode input.fgetws((wchar_t *)P1,MAX_PATH,stdin);eol=wcspbrk((wchar_t *)P1,L"\r\n");if (eol!=NULL)*eol=0;}return(1);default:return(1);}}if (P2==RAR_VOL_NOTIFY)printf("\n  ... volume %S\n",(wchar_t *)P1);return(1);case UCM_PROCESSDATA:if (UserData==PRINT){fflush(stdout);fwrite((char *)P1,1,P2,stdout);fflush(stdout);}return(1);case UCM_NEEDPASSWORDW:{wchar_t *eol;printf("\nPassword required: ");// fgetws may fail to read non-English characters from stdin// in some compilers. In this case use something more appropriate// for Unicode input.fgetws((wchar_t *)P1,(int)P2,stdin);eol=wcspbrk((wchar_t *)P1,L"\r\n");if (eol!=NULL)*eol=0;}return(1);}return(0);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/133701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试—如何介绍项目中的多级缓存?

项目中使用的多级缓存也就是 分布式缓存 Redis 本地缓存 Caffeine&#xff0c;那么令 Caffeine 作为一级缓存&#xff0c;Redis 作为二级缓存&#xff0c;在项目中通过记录数据的访问次数&#xff0c;将热点数据放在 本地缓存&#xff0c;将非热点数据放在 Redis缓存 中&#…

11月1日 mybatis入门

java程序与数据库对接端: jdbc 步骤固定, 代码固定, 大量重复代码 SQL写在代码中, 修改sql,需要重新编译代码, 动态sql, 手动拼接 结果集与java对象转换, java程序与前端对接端: javaWeb 手动获取请求参数, 需要手动进行数据转换 一个请求对应一个Servlet,造成Servlet类暴增…

【MongoDB】索引 - 复合索引

一、准备工作 这里准备一些学生数据 db.students.insertMany([{ _id: 1, name: "张三", age: 20, class: { id: 1, name: "1班" }},{ _id: 2, name: "李四", age: 22, class: { id: 2, name: "2班" }},{ _id: 3, name: "王五…

2023年最热门的五大编程技术趋势

2023年最热门的五大编程技术趋势 摘要&#xff1a;本文将介绍2023年最热门的五大编程技术趋势&#xff0c;包括人工智能、区块链、WebAssembly、5G和边缘计算以及自动化。我们将详细讨论这些趋势的当前状态、未来展望以及如何利用这些技术来提高您的编程技能。 一、前言 随着…

linux+python3.6.8+uwsgi+postgresql+django部署web服务器

linuxpython3.6.8uwsgipostgresqldjango部署web服务器 1.查看系统信息2.配置postgresql数据库2-1.安装postgresql数据库2-2.设置密码2-3.修改postgresql数据库配置文件 3.Python虚拟环境激活虚拟环境 4.Django4-1.Python 安装Django4-2.创建Django项目4-3.配置Django 5.uwsgi5-…

解决docker tag打标签时报错:Error response from daemon: no such id

现象&#xff1a; 原因&#xff1a; docker tag时不仅仅要Repository仓库名&#xff0c;也需要原有的tag作为版本号 解决办法&#xff1a; docker tag 原有仓库名: 原有tag值 新的打标名称 问题解决&#xff01;

【vue3/高德地图】实现地图打点/自定义点位图标/地理围栏实现

<template><div class"app-container"><div id"container"></div></div> </template><script setup> import AMapLoader from amap/amap-jsapi-loader; /*在Vue3中使用时,需要引入Vue3中的shallowRef方法(使用s…

响应式编程-Project Reactor Mono 介绍

响应式编程-Project Reactor Mono 介绍 本文以Mono的角度来介绍Reactor编程&#xff0c;Flux的使用同理。 初体验 Web应用 controller 方法在Spring webmvc 和 Spring webFlux下Controller方法实现示例如下&#xff1a; Spring webmvc: GetMapping("/test1") …

【bug-maven】(一)java: 错误: 不支持发行版本 5 (二):java: 错误: 无效的源发行版:15

【bug-maven】&#xff08;一&#xff09;java: 错误: 不支持发行版本 5 &#xff08;二&#xff09;&#xff1a;java: 错误: 无效的源发行版&#xff1a;15 &#xff08;一&#xff09;java: 错误: 不支持发行版本 5 报错截图&#xff1a; 出错原因&#xff1a; 打开Projec…

SpringBoot整合EasyExcel

springboot整合easyExcel的全流程&#xff0c;跟着做就能出来。对项目没有侵入要求。0侵入&#xff0c;可插拔 依赖 <!--操作Excel依赖--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>…

docker存储卷

docker存储卷 COW机制 Docker镜像由多个只读层叠加而成&#xff0c;启动容器时&#xff0c;Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。 如果运行中的容器修改了现有的一个已经存在的 文件&#xff0c;那么该文件将会从读写层下面的只读层复制到读写层&#xff0…

AI人工智能大模型业务到底有多烧钱?

AI大模型业务确实是一个非常烧钱的行业。首先&#xff0c;大模型的训练需要大量的计算资源。 这些模型通常由数百万个参数组成&#xff0c;训练它们需要大量的计算能力和存储空间。这意味着公司需要购买大量的高性能服务器、图形处理单元和存储设备&#xff0c;这些都是非常昂…

QT学习之QT概述

1.1 什么是QT&#xff1f; Qt是一个跨平台的C图形用户界面应用程序框架。 QT特点&#xff1a; 跨平台&#xff0c;几乎支持所有的平台接口简单&#xff0c;容易上手&#xff0c;学习QT框架对学习其他框架有参考意义。一定程度上简化了内存回收机制开发效率高&#xff0c;能够…

使用lua-resty-request库编写爬虫IP实现数据抓取

目录 一、lua-resty-request库介绍 二、使用lua-resty-request库进行IP数据抓取 1、获取IP地址 2、设置请求 3、处理数据 三、代码实现 四、注意事项 五、总结 本文将深入探讨如何使用lua-resty-request库在爬虫程序中实现IP数据抓取。我们将首先介绍lua-resty-request…

【算法|二分查找No.2】leetcode 69. x 的平方根

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

【Docker】Docker中 的AUFS、BTRFS、ZFS、存储池概念的详细讲解

前言 作者简介&#xff1a; 辭七七&#xff0c;目前大二&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&…

Apache Doris (五十二): Doris Join类型 - Broadcast Join

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. Broadcast Join原理

接口测试及接口测试工具

首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能给你…

DocTemplateTool - 可根据模板生成word或pdf文件的工具

你是否经常遇到这样的场景&#xff1a;产品运营有着大量的报告需求&#xff0c;或者给客户领导展现每周的运营报告&#xff1f;这些文档类的任务可以交给运营同事&#xff0c;他们负责文档排版和样式&#xff0c;你作为开发人员你只需要提供数据源&#xff0c;和一个映射表&…

Elasticsearch:在 ES|QL 中使用 DISSECT 和 GROK 进行数据处理

目录 DISSECT 还是 GROK&#xff1f; 或者两者兼而有之&#xff1f; 使用 DISSECT 处理数据 Dissect pattern 术语 例子 DISSECT 关键修饰符 右填充修饰符 (->) 附加修饰符 () 添加顺序修饰符&#xff08; 和 /n&#xff09; 命名的跳过键&#xff08;&#xff1f…