• 使用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文件到指定的目录,修改比较简单,这里直接上代码:

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include "unrar.h"
    8. enum { EXTRACT, TEST, PRINT, LIST };
    9. int CommandLine(int Argc, char *Argv[]);
    10. void ExtractArchive(char *ArcName,int Mode);
    11. void ExtractArchive(char *ArcName, char* DstDir);
    12. void ListArchive(char *ArcName);
    13. size_t ListArchive(char *ArcName, std::vector& vFiles);
    14. void ShowComment(wchar_t *CmtBuf);
    15. void OutHelp(void);
    16. enum ERR_TYPE {ERR_OPEN, ERR_READ, ERR_PROCESS};
    17. void OutError(int Error,char *ArcName,int ErrType);
    18. void ShowArcInfo(unsigned int Flags,char *ArcName);
    19. void PrintTime(const char *Label,unsigned int Low,unsigned int High);
    20. void OutProcessFileError(int Error);
    21. int CALLBACK CallbackProc(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);

    实现文件:

    1. #define STRICT
    2. #include "UnRDLL.h"
    3. int CommandLine(int Argc, char *Argv[])
    4. {
    5. setlocale(LC_ALL, NULL);
    6. if (Argc!=3)
    7. {
    8. OutHelp();
    9. return(0);
    10. }
    11. switch(toupper(Argv[1][0]))
    12. {
    13. case 'X':
    14. ExtractArchive(Argv[2],EXTRACT);
    15. break;
    16. case 'T':
    17. ExtractArchive(Argv[2],TEST);
    18. break;
    19. case 'P':
    20. ExtractArchive(Argv[2],PRINT);
    21. break;
    22. case 'L':
    23. ListArchive(Argv[2]);
    24. break;
    25. default:
    26. OutHelp();
    27. return(0);
    28. }
    29. return(0);
    30. }
    31. void ExtractArchive(char *ArcName,int Mode)
    32. {
    33. HANDLE hArcData;
    34. int RHCode,PFCode;
    35. wchar_t CmtBuf[16384];
    36. struct RARHeaderData HeaderData;
    37. struct RAROpenArchiveDataEx OpenArchiveData;
    38. memset(&HeaderData,0,sizeof(HeaderData));
    39. memset(&OpenArchiveData,0,sizeof(OpenArchiveData));
    40. OpenArchiveData.ArcName=ArcName;
    41. OpenArchiveData.CmtBufW=CmtBuf;
    42. OpenArchiveData.CmtBufSize=sizeof(CmtBuf)/sizeof(CmtBuf[0]);
    43. OpenArchiveData.OpenMode=RAR_OM_EXTRACT;
    44. OpenArchiveData.Callback=CallbackProc;
    45. OpenArchiveData.UserData=Mode;
    46. hArcData=RAROpenArchiveEx(&OpenArchiveData);
    47. if (OpenArchiveData.OpenResult!=0)
    48. {
    49. OutError(OpenArchiveData.OpenResult,ArcName,ERR_OPEN);
    50. return;
    51. }
    52. ShowArcInfo(OpenArchiveData.Flags,ArcName);
    53. if (OpenArchiveData.CmtState==1)
    54. ShowComment(CmtBuf);
    55. while ((RHCode=RARReadHeader(hArcData,&HeaderData))==0)
    56. {
    57. switch(Mode)
    58. {
    59. case EXTRACT:
    60. printf("\nExtracting %-45s",HeaderData.FileName);
    61. break;
    62. case TEST:
    63. printf("\nTesting %-45s",HeaderData.FileName);
    64. break;
    65. case PRINT:
    66. printf("\nPrinting %-45s\n",HeaderData.FileName);
    67. break;
    68. }
    69. PFCode=RARProcessFile(hArcData,(Mode==EXTRACT) ? RAR_EXTRACT:RAR_TEST,
    70. NULL,NULL);
    71. if (PFCode==0)
    72. printf(" OK");
    73. else
    74. {
    75. OutError(PFCode,ArcName,ERR_PROCESS);
    76. break;
    77. }
    78. }
    79. OutError(RHCode,ArcName,ERR_READ);
    80. RARCloseArchive(hArcData);
    81. }
    82. void ExtractArchive(char *ArcName, char* DstDir)
    83. {
    84. HANDLE hArcData;
    85. int RHCode,PFCode;
    86. wchar_t CmtBuf[16384];
    87. struct RARHeaderData HeaderData;
    88. struct RAROpenArchiveDataEx OpenArchiveData;
    89. memset(&HeaderData,0,sizeof(HeaderData));
    90. memset(&OpenArchiveData,0,sizeof(OpenArchiveData));
    91. OpenArchiveData.ArcName=ArcName;
    92. OpenArchiveData.CmtBufW=CmtBuf;
    93. OpenArchiveData.CmtBufSize=sizeof(CmtBuf)/sizeof(CmtBuf[0]);
    94. OpenArchiveData.OpenMode=RAR_OM_EXTRACT;
    95. OpenArchiveData.Callback=CallbackProc;
    96. OpenArchiveData.UserData= EXTRACT;
    97. hArcData=RAROpenArchiveEx(&OpenArchiveData);
    98. if (OpenArchiveData.OpenResult!=0)
    99. {
    100. OutError(OpenArchiveData.OpenResult,ArcName,ERR_OPEN);
    101. return;
    102. }
    103. ShowArcInfo(OpenArchiveData.Flags,ArcName);
    104. if (OpenArchiveData.CmtState==1)
    105. ShowComment(CmtBuf);
    106. while ((RHCode=RARReadHeader(hArcData,&HeaderData))==0)
    107. {
    108. printf("\nExtracting %-45s",HeaderData.FileName);
    109. PFCode=RARProcessFile(hArcData,RAR_EXTRACT,DstDir,NULL);
    110. if (PFCode==0)
    111. printf(" OK");
    112. else
    113. {
    114. OutError(PFCode,ArcName,ERR_PROCESS);
    115. break;
    116. }
    117. }
    118. OutError(RHCode,ArcName,ERR_READ);
    119. RARCloseArchive(hArcData);
    120. }
    121. size_t ListArchive(char *ArcName, std::vector& vFiles)
    122. {
    123. HANDLE hArcData;
    124. int RHCode,PFCode;
    125. wchar_t CmtBuf[16384];
    126. struct RARHeaderDataEx HeaderData;
    127. struct RAROpenArchiveDataEx OpenArchiveData;
    128. wchar_t RedirName[1024];
    129. memset(&HeaderData,0,sizeof(HeaderData));
    130. memset(&OpenArchiveData,0,sizeof(OpenArchiveData));
    131. OpenArchiveData.ArcName=ArcName;
    132. OpenArchiveData.CmtBufW=CmtBuf;
    133. OpenArchiveData.CmtBufSize=sizeof(CmtBuf)/sizeof(CmtBuf[0]);
    134. OpenArchiveData.OpenMode=RAR_OM_LIST;
    135. OpenArchiveData.Callback=CallbackProc;
    136. OpenArchiveData.UserData=LIST;
    137. hArcData=RAROpenArchiveEx(&OpenArchiveData);
    138. if (OpenArchiveData.OpenResult!=0)
    139. {
    140. OutError(OpenArchiveData.OpenResult,ArcName,ERR_OPEN);
    141. return 0;
    142. }
    143. ShowArcInfo(OpenArchiveData.Flags,ArcName);
    144. if (OpenArchiveData.CmtState==1)
    145. ShowComment(CmtBuf);
    146. HeaderData.RedirName=RedirName;
    147. HeaderData.RedirNameSize=sizeof(RedirName)/sizeof(RedirName[0]);
    148. while ((RHCode=RARReadHeaderEx(hArcData,&HeaderData))==0)
    149. {
    150. __int64 UnpSize=HeaderData.UnpSize+(((__int64)HeaderData.UnpSizeHigh)<<32);
    151. __int64 PackSize=HeaderData.PackSize+(((__int64)HeaderData.PackSizeHigh)<<32);
    152. printf("\nName: %s",HeaderData.FileName);
    153. vFiles.push_back(HeaderData.FileName);
    154. printf("\nSize: %lld ",UnpSize);
    155. printf("\nPacked: %lld ",PackSize);
    156. PrintTime("mtime",HeaderData.MtimeLow,HeaderData.MtimeHigh);
    157. PrintTime("ctime",HeaderData.CtimeLow,HeaderData.CtimeHigh);
    158. PrintTime("atime",HeaderData.AtimeLow,HeaderData.AtimeHigh);
    159. if (HeaderData.RedirType!=0)
    160. printf("\n\tlink type %d, target %ls",HeaderData.RedirType,HeaderData.RedirName);
    161. if ((PFCode=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL))!=0)
    162. {
    163. OutError(PFCode,ArcName,ERR_PROCESS);
    164. break;
    165. }
    166. printf("\n");
    167. }
    168. OutError(RHCode,ArcName,ERR_READ);
    169. RARCloseArchive(hArcData);
    170. return vFiles.size();
    171. }
    172. void ListArchive(char *ArcName)
    173. {
    174. HANDLE hArcData;
    175. int RHCode,PFCode;
    176. wchar_t CmtBuf[16384];
    177. struct RARHeaderDataEx HeaderData;
    178. struct RAROpenArchiveDataEx OpenArchiveData;
    179. wchar_t RedirName[1024];
    180. memset(&HeaderData,0,sizeof(HeaderData));
    181. memset(&OpenArchiveData,0,sizeof(OpenArchiveData));
    182. OpenArchiveData.ArcName=ArcName;
    183. OpenArchiveData.CmtBufW=CmtBuf;
    184. OpenArchiveData.CmtBufSize=sizeof(CmtBuf)/sizeof(CmtBuf[0]);
    185. OpenArchiveData.OpenMode=RAR_OM_LIST;
    186. OpenArchiveData.Callback=CallbackProc;
    187. OpenArchiveData.UserData=LIST;
    188. hArcData=RAROpenArchiveEx(&OpenArchiveData);
    189. if (OpenArchiveData.OpenResult!=0)
    190. {
    191. OutError(OpenArchiveData.OpenResult,ArcName,ERR_OPEN);
    192. return;
    193. }
    194. ShowArcInfo(OpenArchiveData.Flags,ArcName);
    195. if (OpenArchiveData.CmtState==1)
    196. ShowComment(CmtBuf);
    197. HeaderData.RedirName=RedirName;
    198. HeaderData.RedirNameSize=sizeof(RedirName)/sizeof(RedirName[0]);
    199. while ((RHCode=RARReadHeaderEx(hArcData,&HeaderData))==0)
    200. {
    201. __int64 UnpSize=HeaderData.UnpSize+(((__int64)HeaderData.UnpSizeHigh)<<32);
    202. __int64 PackSize=HeaderData.PackSize+(((__int64)HeaderData.PackSizeHigh)<<32);
    203. printf("\nName: %s",HeaderData.FileName);
    204. printf("\nSize: %lld ",UnpSize);
    205. printf("\nPacked: %lld ",PackSize);
    206. PrintTime("mtime",HeaderData.MtimeLow,HeaderData.MtimeHigh);
    207. PrintTime("ctime",HeaderData.CtimeLow,HeaderData.CtimeHigh);
    208. PrintTime("atime",HeaderData.AtimeLow,HeaderData.AtimeHigh);
    209. if (HeaderData.RedirType!=0)
    210. printf("\n\tlink type %d, target %ls",HeaderData.RedirType,HeaderData.RedirName);
    211. if ((PFCode=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL))!=0)
    212. {
    213. OutError(PFCode,ArcName,ERR_PROCESS);
    214. break;
    215. }
    216. printf("\n");
    217. }
    218. OutError(RHCode,ArcName,ERR_READ);
    219. RARCloseArchive(hArcData);
    220. }
    221. void ShowComment(wchar_t *CmtBuf)
    222. {
    223. printf("\nComment:\n%ls\n",CmtBuf);
    224. }
    225. void OutHelp(void)
    226. {
    227. printf("\nUNRDLL. This is a simple example of UNRAR.DLL usage\n");
    228. printf("\nSyntax:\n");
    229. printf("\nUNRDLL X extract archive contents");
    230. printf("\nUNRDLL T test archive contents");
    231. printf("\nUNRDLL P print archive contents to stdout");
    232. printf("\nUNRDLL L view archive contents\n");
    233. }
    234. void OutError(int Error,char *ArcName,int ErrType)
    235. {
    236. switch(Error)
    237. {
    238. case ERAR_NO_MEMORY:
    239. printf("\nNot enough memory");
    240. break;
    241. case ERAR_BAD_DATA:
    242. printf("\n%s: archive header or data are damaged",ArcName);
    243. break;
    244. case ERAR_BAD_ARCHIVE:
    245. printf("\n%s is not RAR archive",ArcName);
    246. break;
    247. case ERAR_UNKNOWN_FORMAT:
    248. printf("Unknown archive format");
    249. break;
    250. case ERAR_EOPEN:
    251. if (ErrType==ERR_PROCESS) // Returned by RARProcessFile.
    252. printf("Volume open error");
    253. else
    254. printf("\nCannot open %s",ArcName);
    255. break;
    256. case ERAR_ECREATE:
    257. printf("File create error");
    258. break;
    259. case ERAR_ECLOSE:
    260. printf("File close error");
    261. break;
    262. case ERAR_EREAD:
    263. printf("Read error");
    264. break;
    265. case ERAR_EWRITE:
    266. printf("Write error");
    267. break;
    268. case ERAR_SMALL_BUF:
    269. printf("Buffer for archive comment is too small, comment truncated");
    270. break;
    271. case ERAR_UNKNOWN:
    272. printf("Unknown error");
    273. break;
    274. case ERAR_MISSING_PASSWORD:
    275. printf("Password for encrypted file or header is not specified");
    276. break;
    277. case ERAR_EREFERENCE:
    278. printf("Cannot open file source for reference record");
    279. break;
    280. case ERAR_BAD_PASSWORD:
    281. printf("Wrong password is specified");
    282. break;
    283. }
    284. }
    285. void ShowArcInfo(unsigned int Flags,char *ArcName)
    286. {
    287. printf("\nArchive %s\n",ArcName);
    288. printf("\nVolume:\t\t%s",(Flags & 1) ? "yes":"no");
    289. printf("\nComment:\t%s",(Flags & 2) ? "yes":"no");
    290. printf("\nLocked:\t\t%s",(Flags & 4) ? "yes":"no");
    291. printf("\nSolid:\t\t%s",(Flags & 8) ? "yes":"no");
    292. printf("\nNew naming:\t%s",(Flags & 16) ? "yes":"no");
    293. printf("\nRecovery:\t%s",(Flags & 64) ? "yes":"no");
    294. printf("\nEncr.headers:\t%s",(Flags & 128) ? "yes":"no");
    295. printf("\nFirst volume:\t%s",(Flags & 256) ? "yes":"no or older than 3.0");
    296. printf("\n---------------------------\n");
    297. }
    298. void PrintTime(const char *Label,unsigned int Low,unsigned int High)
    299. {
    300. if (Low!=0 || High!=0)
    301. {
    302. FILETIME ft;
    303. ft.dwLowDateTime=Low;
    304. ft.dwHighDateTime=High;
    305. SYSTEMTIME ust,st;
    306. FileTimeToSystemTime(&ft,&ust);
    307. SystemTimeToTzSpecificLocalTime(NULL,&ust,&st);
    308. printf("\n%s: %u-%02u-%02u %02u:%02u:%02u,%03u",Label,st.wYear,st.wMonth,
    309. st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
    310. }
    311. }
    312. int CALLBACK CallbackProc(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2)
    313. {
    314. switch(msg)
    315. {
    316. case UCM_CHANGEVOLUMEW:
    317. if (P2==RAR_VOL_ASK)
    318. {
    319. printf("\n\nVolume %S is required\nPossible options:\n",(wchar_t *)P1);
    320. printf("\nEnter - try again");
    321. printf("\n'R' - specify a new volume name");
    322. printf("\n'Q' - quit");
    323. printf("\nEnter your choice: ");
    324. switch(toupper(getchar()))
    325. {
    326. case 'Q':
    327. return(-1);
    328. case 'R':
    329. {
    330. wchar_t *eol;
    331. printf("\nEnter new name: ");
    332. fflush(stdin);
    333. // fgetws may fail to read non-English characters from stdin
    334. // in some compilers. In this case use something more
    335. // appropriate for Unicode input.
    336. fgetws((wchar_t *)P1,MAX_PATH,stdin);
    337. eol=wcspbrk((wchar_t *)P1,L"\r\n");
    338. if (eol!=NULL)
    339. *eol=0;
    340. }
    341. return(1);
    342. default:
    343. return(1);
    344. }
    345. }
    346. if (P2==RAR_VOL_NOTIFY)
    347. printf("\n ... volume %S\n",(wchar_t *)P1);
    348. return(1);
    349. case UCM_PROCESSDATA:
    350. if (UserData==PRINT)
    351. {
    352. fflush(stdout);
    353. fwrite((char *)P1,1,P2,stdout);
    354. fflush(stdout);
    355. }
    356. return(1);
    357. case UCM_NEEDPASSWORDW:
    358. {
    359. wchar_t *eol;
    360. printf("\nPassword required: ");
    361. // fgetws may fail to read non-English characters from stdin
    362. // in some compilers. In this case use something more appropriate
    363. // for Unicode input.
    364. fgetws((wchar_t *)P1,(int)P2,stdin);
    365. eol=wcspbrk((wchar_t *)P1,L"\r\n");
    366. if (eol!=NULL)
    367. *eol=0;
    368. }
    369. return(1);
    370. }
    371. return(0);
    372. }

  • 相关阅读:
    linux-硬盘
    实验四-----数据库
    .NET Evolve 数据库版本管理工具
    一起Talk Android吧(第三百六十六回:多线程之LOCK锁)
    分片集群中的分片集合
    [数据可视化] 漏斗图(Funnel Chart)
    Java 面试题:对比 Hashtable、HashMap、TreeMap 有什么不同?
    推荐几款好看又好用的开源博客
    ttkefu在线客服在日常生活中的便利性体验
    Docker部署Portainer图形化管理工具
  • 原文地址:https://blog.csdn.net/autumoonchina/article/details/134272915