c++ 下载并解压 .7z 格式的文件并在dialog对话框上显示进度条使用mfc
时间: 2023-11-28 13:48:48 浏览: 94
你可以使用第三方库如7zip来解压.7z文件,并使用MFC中的CProgressCtrl控件来实现进度条的显示。
以下是一个简单的示例代码:
```c++
#include "stdafx.h"
#include "MyDialog.h"
#include "7zip/7z.h"
#include "7zip/7zAlloc.h"
#include "7zip/7zFile.h"
#include <afxinet.h>
#define kBufferSizeMax (1 << 22)
BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON_UNZIP, &CMyDialog::OnBnClickedButtonUnzip)
END_MESSAGE_MAP()
CMyDialog::CMyDialog(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_MYDIALOG_DIALOG, pParent)
{
}
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_PROGRESS_UNZIP, m_progressUnzip);
}
BOOL CMyDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
m_progressUnzip.SetRange(0, 100);
return TRUE;
}
void CMyDialog::OnBnClickedButtonUnzip()
{
CString strSourceFilePath = _T("D:\\test.7z");
CString strDestFolderPath = _T("D:\\test");
// 打开源文件
HANDLE hSourceFile = CreateFile(strSourceFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hSourceFile == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("打开源文件失败!"));
return;
}
// 获取源文件大小
LARGE_INTEGER liFileSize;
if (!GetFileSizeEx(hSourceFile, &liFileSize))
{
AfxMessageBox(_T("获取源文件大小失败!"));
CloseHandle(hSourceFile);
return;
}
// 打开7z文件
CFileInStream archiveStream;
if (InFile_Open(&archiveStream.file, hSourceFile))
{
AfxMessageBox(_T("打开7z文件失败!"));
CloseHandle(hSourceFile);
return;
}
archiveStream.s.Read = InFile_Read;
archiveStream.s.Seek = InFile_Seek;
// 获取7z文件头
CLookToRead2 lookStream;
LookToRead2_CreateVTable(lookStream, False);
lookStream.realStream = &archiveStream.s;
LookToRead2_Init(&lookStream);
CrcGenerateTable();
Byte header[kHeaderSize];
unsigned headerSize = kHeaderSize;
int result = ReadHeader(&lookStream.s, header, &headerSize);
if (result != SZ_OK)
{
AfxMessageBox(_T("获取7z文件头失败!"));
InFile_Close(&archiveStream.file);
CloseHandle(hSourceFile);
return;
}
// 获取解压文件列表
CSzArEx db;
SzArEx_Init(&db);
result = SzArEx_Open(&db, &lookStream.s, &g_Alloc, &g_Alloc);
if (result != SZ_OK)
{
AfxMessageBox(_T("获取解压文件列表失败!"));
SzArEx_Free(&db, &g_Alloc);
InFile_Close(&archiveStream.file);
CloseHandle(hSourceFile);
return;
}
// 创建目标目录
if (!CreateDirectory(strDestFolderPath, NULL))
{
DWORD dwError = GetLastError();
if (dwError != ERROR_ALREADY_EXISTS)
{
AfxMessageBox(_T("创建目标目录失败!"));
SzArEx_Free(&db, &g_Alloc);
InFile_Close(&archiveStream.file);
CloseHandle(hSourceFile);
return;
}
}
// 解压文件
int i;
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
CFileOutStream *fileStream = NULL;
for (i = 0; i < db.db.NumFiles; i++)
{
CString strFilePath = strDestFolderPath + _T("\\") + CString(db.FileName[i]);
// 创建目标文件
fileStream = new CFileOutStream();
if (OutFile_Open(&fileStream->file, strFilePath))
{
AfxMessageBox(_T("创建目标文件失败!"));
delete fileStream;
fileStream = NULL;
continue;
}
// 获取文件大小
UInt64 fileSize = SzArEx_GetFileSize(&db, i);
// 更新进度条
int nProgress = static_cast<int>(100 * fileStream->pos / fileSize);
m_progressUnzip.SetPos(nProgress);
// 解压文件
SzExtractFlags extractFlags;
SzArEx_GetExtractSettings(&db, i, &extractFlags);
result = SzArEx_Extract(&db, &lookStream.s, i,
&blockIndex, &outBuffer, &outBufferSize,
&fileStream->s, &fileStream->file, &g_Alloc, &g_Alloc);
if (result != SZ_OK)
{
AfxMessageBox(_T("解压文件失败!"));
delete fileStream;
fileStream = NULL;
continue;
}
// 关闭目标文件
OutFile_Close(&fileStream->file);
delete fileStream;
fileStream = NULL;
}
// 清理
SzArEx_Free(&db, &g_Alloc);
if (outBuffer)
g_Alloc.Free(outBuffer);
InFile_Close(&archiveStream.file);
CloseHandle(hSourceFile);
AfxMessageBox(_T("解压完成!"));
}
```
在该示例中,我们使用了7zip库来解压.7z文件,并实现了一个简单的进度条来显示解压进度。
请注意,此示例仅供参考,请根据自己的需求进行修改和优化。
阅读全文