Windows Practice_文件_文件分割器(三)
来源:互联网 发布:linux 线程退出 编辑:程序博客网 时间:2024/06/17 09:08
两种开发方式
- 瀑布式开发
有需求 -> 分析 -> 建模 -> 编码 -> 维护 所有的类全部是自己设计编码的 - 敏捷开发
需求 -> 编码 -> 重构(建模) -> 编码 需求总是变化的 -> 代码也需要变化
所谓的敏捷开发就是拿着开源项目修改为自己的项目,随着时间的推移,改变的越来越多的内容,最后可能将原来开源项目中的所有内容都改为自己的内容。
当前类的性质,
类方法及类成员设计的时候
1. 方法及成员的时间和空间取舍
2. 类和类之间除了继承等之外,没有任何关系,每个类只负责把本类的业务逻辑处理好就可以了。
针对这些问题,将原来的文件分割少做了一些改进,其中包括CMyPartFile类的逻辑改进以及多线程的使用,多线程使得在处理大文件的时候,不会让界面卡死。
下面是代码,直接直接贴上去了:
//MySplitAndMerge.h文件#pragma once#include <vector>class CMyPartFile : public CFile{public: enum eModal { MODAL_SPLIT, MODAL_MERGE };private: typedef struct tagPartFileNameHeader { WORD wFlag; WCHAR wstrFirstFileName[MAX_PATH]; WCHAR wstrNextFileName[MAX_PATH]; UINT uOriginalFileSize; } PARTFILENAMEHEADER;public: // 构造的时候只是负责打开或者创建一个文件,这个需要根据模式来定 // 算了,还是不在构造函数中进行打开或者创建了,在构造函数中只做参数的配置 // 如果是分割,那么就在保存的时候进行打开,写入 // 如果是合并,就在获取数据的时候进行打开,读取 CMyPartFile(const CString strFilePath, eModal modal); ~CMyPartFile(); BOOL IsValidPartFile(BOOL bNeedClose); WCHAR *GetFirstFileName(); WCHAR *GetNextFileName(); UINT GetOriginalFileSize() const; BOOL SaveDataToFile(WORD wFlag, CString strFirstFileName, CString strNextFileName, UINT uOriginalFileSize, const BYTE *pByte); UINT GetDataFromFile(BYTE *pByte);private: void CheckPartFileHeader(); // 这个函数有待于验证是否有必要存在 BOOL MyOpenFile();private: PARTFILENAMEHEADER m_partFileNameHeader; CString m_strFilePath; eModal m_modal; BOOL m_bInitPartFileHeader;};// 专门操作CMyPartFile类的类class CMySplitAndMerge{public: /** * \brief * \param strFolderName 待分割文件所在的文件夹名字 * \param strFileName 待分割文件的名字 * \param bSplitByFileSize 分割的类型: * \param uNumber * \return */ BOOL Split(const CString strFolderName, const CString strFileName, BOOL bSplitByFileSize, UINT uNumber); BOOL Merge(const CString strFolderName, const CString strFileName, const CString strDestFileName);private: BOOL MyOpenFile(CFile& file, const CString strFilePath, BOOL bRead) const; CString CreateDir(const CString strFileName); /** * \brief 根据分割文件的个数计算出分割文件的大小 * \param strFilePath 待分割文件路径 * \param uNumber 待分割文件个数 * \return 如果返货0,表示计算失败,否则返回每个分割文件的大小 */ UINT CalcFileSize(const CString strFilePath, UINT uFileNumber) const; BOOL SplitFileByFileSize(const CString strFolderName, const CString strFilePath, UINT uFileSize) const; BOOL GetAllPartFile(const CString strFolderName, const CString strFileName);private: std::vector<CMyPartFile *> m_vecMyPartFile;};
#include "stdafx.h"#include "MySplitAndMerge.h"//MySplitAndMerge.cpp文件CMyPartFile::CMyPartFile(const CString strFilePath, eModal modal) : CFile(), m_strFilePath(strFilePath), m_modal(modal), m_bInitPartFileHeader(FALSE){}CMyPartFile::~CMyPartFile(){}BOOL CMyPartFile::IsValidPartFile(BOOL bNeedClose){ CheckPartFileHeader(); if (bNeedClose) { Close(); } return m_partFileNameHeader.wFlag == MAKEWORD('P', 'o');}WCHAR* CMyPartFile::GetFirstFileName(){ return m_partFileNameHeader.wstrFirstFileName;}WCHAR* CMyPartFile::GetNextFileName(){ return m_partFileNameHeader.wstrNextFileName;}UINT CMyPartFile::GetOriginalFileSize() const{ return m_partFileNameHeader.uOriginalFileSize;}BOOL CMyPartFile::SaveDataToFile(WORD wFlag, CString strFirstFileName, CString strNextFileName, UINT uOriginalFileSize, const BYTE *pByte){ m_partFileNameHeader.wFlag = wFlag; wcscpy_s(m_partFileNameHeader.wstrFirstFileName, strFirstFileName); wcscpy_s(m_partFileNameHeader.wstrNextFileName, strNextFileName); m_partFileNameHeader.uOriginalFileSize = uOriginalFileSize; BOOL bRet = TRUE; if (MyOpenFile()) { Write(&m_partFileNameHeader, sizeof(PARTFILENAMEHEADER)); Write(pByte, uOriginalFileSize); Close(); } else { bRet = FALSE; } return bRet;}UINT CMyPartFile::GetDataFromFile(BYTE* pByte){ UINT uReadByte = 0; if (m_partFileNameHeader.uOriginalFileSize == Read(pByte, m_partFileNameHeader.uOriginalFileSize)) { uReadByte = m_partFileNameHeader.uOriginalFileSize; } Close(); return uReadByte;}void CMyPartFile::CheckPartFileHeader(){ if (!m_bInitPartFileHeader) { MyOpenFile(); if (Read(&m_partFileNameHeader, sizeof(PARTFILENAMEHEADER)) == sizeof(PARTFILENAMEHEADER)) { m_bInitPartFileHeader = TRUE; } }}BOOL CMyPartFile::MyOpenFile(){ BOOL bRet = FALSE; WCHAR strErrorMessage[MAXBYTE] = { 0 }; CFileException fileException; UINT nOpenFlags = CFile::typeBinary; if (MODAL_SPLIT == m_modal) { nOpenFlags |= (CFile::modeCreate | CFile::modeWrite); } else { nOpenFlags |= CFile::modeRead; } if (Open(m_strFilePath, nOpenFlags, &fileException)) { bRet = TRUE; } else { fileException.GetErrorMessage(strErrorMessage, MAXBYTE); AfxMessageBox(strErrorMessage); } return bRet;}BOOL CMySplitAndMerge::Split(const CString strFolderName, const CString strFileName, BOOL bSplitByFileSize, UINT uNumber){ BOOL bRet = FALSE; UINT uFileSize = uNumber; if (!bSplitByFileSize) { uFileSize = CalcFileSize(strFolderName + L"\\" + strFileName, uNumber); } if (uFileSize > 0) { // 开始分割文件 CString strDirName; strDirName = CreateDir(strFileName); CreateDirectory(strFolderName + L"\\" + strDirName, nullptr); bRet = SplitFileByFileSize(strFolderName + L"\\" + strDirName, strFolderName + L"\\" + strFileName, uFileSize); } else { AfxMessageBox(TEXT("分割的文件大小不能为0")); } return bRet;}BOOL CMySplitAndMerge::Merge(const CString strFolderName, const CString strFileName, const CString strDestFileName){ BOOL bRet = TRUE; if (GetAllPartFile(strFolderName, strFileName)) { CFile file; if (MyOpenFile(file, strFolderName + L"\\" + strDestFileName, FALSE)) { for (auto value : m_vecMyPartFile) { UINT uOriginalFileSize = value->GetOriginalFileSize(); BYTE *pByte = new BYTE[uOriginalFileSize]; memset(pByte, 0, uOriginalFileSize); UINT uReadFileLength = value->GetDataFromFile(pByte); if (uReadFileLength != uOriginalFileSize) { bRet = FALSE; break; } file.Write(pByte, uReadFileLength); } file.Close(); m_vecMyPartFile.clear(); } } return bRet;}BOOL CMySplitAndMerge::MyOpenFile(CFile& file, const CString strFilePath, BOOL bRead) const{ CFileException fileException; UINT nOpenFlags = CFile::typeBinary; if (bRead) { nOpenFlags |= CFile::modeRead; } else { nOpenFlags |= (CFile::modeCreate | CFile::modeWrite); } BOOL bRet = file.Open(strFilePath, nOpenFlags, &fileException); if (!bRet) { WCHAR strErrorMessage[MAXBYTE] = { 0 }; fileException.GetErrorMessage(strErrorMessage, MAXBYTE); bRet = FALSE; AfxMessageBox(strErrorMessage); } return bRet;}CString CMySplitAndMerge::CreateDir(const CString strFileName){ CString strDirName; for (int i = 0; i < strFileName.GetLength(); ++i) { if (strFileName.GetAt(i) != L'.') { strDirName += strFileName.GetAt(i); } else { break; } } return strDirName;}UINT CMySplitAndMerge::CalcFileSize(const CString strFilePath, UINT uFileNumber) const{ UINT uRet = 0; CFile file; if (MyOpenFile(file, strFilePath, TRUE)) { uRet = static_cast<UINT>(file.GetLength() % uFileNumber ? file.GetLength() / uFileNumber + 1 : file.GetLength() / uFileNumber); } return uRet;}BOOL CMySplitAndMerge::SplitFileByFileSize(const CString strFolderName, const CString strFilePath, UINT uFileSize) const{ BOOL bRet = FALSE; BYTE *pByte = new BYTE[uFileSize]; memset(pByte, 0, uFileSize); CFile file; if (MyOpenFile(file, strFilePath, TRUE)) { ULONGLONG ullFileLength = file.GetLength(); ULONGLONG ullReadLength = 0; UINT uReadByteNumber, uPartFileCount = 0; CString strFirstFileName = TEXT("0.part"), strCurFileName, strNextFileName; while (true) { uReadByteNumber = file.Read(pByte, uFileSize); ullReadLength += uReadByteNumber; strCurFileName.Format(L"%s\\%d.part", strFolderName.GetString(), uPartFileCount++); strNextFileName.Format(L"%d.part", uPartFileCount); if (ullReadLength >= ullFileLength) { strNextFileName = L"NULL"; bRet = TRUE; } CMyPartFile myPartFile(strCurFileName, CMyPartFile::MODAL_SPLIT); myPartFile.SaveDataToFile(MAKEWORD('P', 'o'), strFirstFileName, strNextFileName, uReadByteNumber, pByte); if (bRet) { break; } memset(pByte, 0, uFileSize); } } return bRet;}BOOL CMySplitAndMerge::GetAllPartFile(const CString strFolderName, const CString strFileName){ BOOL bRet = FALSE; CMyPartFile myPartFile(strFolderName + L"\\" + strFileName, CMyPartFile::MODAL_MERGE); if (myPartFile.IsValidPartFile(TRUE)) { CString strCurFilePath, strNextFilePath = myPartFile.GetFirstFileName(); while (true) { strCurFilePath = strFolderName + L"\\" + strNextFilePath; CMyPartFile *pFile = new CMyPartFile(strCurFilePath, CMyPartFile::MODAL_MERGE); if (pFile->IsValidPartFile(FALSE)) { m_vecMyPartFile.push_back(pFile); strNextFilePath = pFile->GetNextFileName(); if (strNextFilePath == L"NULL") { bRet = TRUE; break; } strCurFilePath = strFolderName + L"\\" + strNextFilePath; } else { break; } } } return bRet;}
// FileSplitAndMergeDlg.h : 头文件//#pragma once#define WM_MYINFO (WM_USER + 100)class CMySplitAndMerge;// CFileSplitAndMergeDlg 对话框class CFileSplitAndMergeDlg : public CDialogEx{// 构造public: CFileSplitAndMergeDlg(CWnd* pParent = NULL); // 标准构造函数// 对话框数据#ifdef AFX_DESIGN_TIME enum { IDD = IDD_FILESPLITANDMERGE_DIALOG };#endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持// 实现protected: HICON m_hIcon; // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP()public: CMySplitAndMerge *m_pMySplitAndMergeFile; afx_msg void OnBnClickedButtonSplit(); afx_msg void OnBnClickedButtonMerge(); afx_msg LRESULT OnMyInfo(WPARAM wParam, LPARAM lParam); static UINT ThreadFunc(LPVOID pParm);//线程函数的定义 CString m_strFolderName; CString m_strFileName; CString m_strDestFileName; UINT m_uFileSize; BOOL m_bSplitByFileSize; BOOL m_bSplit; CWinThread *m_pThread;};
// FileSplitAndMergeDlg.cpp : 实现文件//#include "stdafx.h"#include "FileSplitAndMerge.h"#include "FileSplitAndMergeDlg.h"#include "afxdialogex.h"#include "MySplitAndMerge.h"#ifdef _DEBUG#define new DEBUG_NEW#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx{public: CAboutDlg();// 对话框数据#ifdef AFX_DESIGN_TIME enum { IDD = IDD_ABOUTBOX };#endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持// 实现protected: DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){ CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)END_MESSAGE_MAP()// CFileSplitAndMergeDlg 对话框CFileSplitAndMergeDlg::CFileSplitAndMergeDlg(CWnd* pParent /*=NULL*/) : CDialogEx(IDD_FILESPLITANDMERGE_DIALOG, pParent){ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CFileSplitAndMergeDlg::DoDataExchange(CDataExchange* pDX){ CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CFileSplitAndMergeDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON_SPLIT, &CFileSplitAndMergeDlg::OnBnClickedButtonSplit) ON_BN_CLICKED(IDC_BUTTON_MERGE, &CFileSplitAndMergeDlg::OnBnClickedButtonMerge) ON_MESSAGE(WM_MYINFO, &CFileSplitAndMergeDlg::OnMyInfo)END_MESSAGE_MAP()// CFileSplitAndMergeDlg 消息处理程序BOOL CFileSplitAndMergeDlg::OnInitDialog(){ CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 m_pMySplitAndMergeFile = new CMySplitAndMerge(); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE}void CFileSplitAndMergeDlg::OnSysCommand(UINT nID, LPARAM lParam){ if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); }}// 如果向对话框添加最小化按钮,则需要下面的代码// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,// 这将由框架自动完成。void CFileSplitAndMergeDlg::OnPaint(){ if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); }}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CFileSplitAndMergeDlg::OnQueryDragIcon(){ return static_cast<HCURSOR>(m_hIcon);}void CFileSplitAndMergeDlg::OnBnClickedButtonSplit(){ CFileDialog fileDlg(TRUE); if (fileDlg.DoModal() == IDOK) { m_bSplit = TRUE; m_bSplitByFileSize = TRUE; m_strFolderName = fileDlg.GetFolderPath(); m_strFileName = fileDlg.GetFileName(); m_uFileSize = 1024 * 1024 * 32; m_pThread = AfxBeginThread(ThreadFunc, this); if (m_pThread == nullptr) { AfxMessageBox(TEXT("线程函数启动失败!")); } }}void CFileSplitAndMergeDlg::OnBnClickedButtonMerge(){ CFileDialog fileDlg(TRUE); if (fileDlg.DoModal() == IDOK) { m_bSplit = FALSE; m_strFolderName = fileDlg.GetFolderPath(); m_strFileName = fileDlg.GetFileName(); m_strDestFileName = L"myFile.txt"; m_pThread = AfxBeginThread(ThreadFunc, this); if (m_pThread == nullptr) { AfxMessageBox(TEXT("线程函数启动失败!")); } }}LRESULT CFileSplitAndMergeDlg::OnMyInfo(WPARAM wParam, LPARAM lParam){ if (wParam == 0) { if (m_bSplit) { ((CButton *)GetDlgItem(IDC_BUTTON_SPLIT))->EnableWindow(FALSE); } else { ((CButton *)GetDlgItem(IDC_BUTTON_MERGE))->EnableWindow(FALSE); } } else { if (m_bSplit) { ((CButton *)GetDlgItem(IDC_BUTTON_SPLIT))->EnableWindow(TRUE); } else { ((CButton *)GetDlgItem(IDC_BUTTON_MERGE))->EnableWindow(TRUE); } } return 0;}UINT CFileSplitAndMergeDlg::ThreadFunc(LPVOID lParam){ CFileSplitAndMergeDlg *pDlg = (CFileSplitAndMergeDlg *)lParam; if (pDlg->m_bSplit) { ::SendMessageW(pDlg->m_hWnd, WM_MYINFO, 0, 0); if (pDlg->m_pMySplitAndMergeFile->Split(pDlg->m_strFolderName, pDlg->m_strFileName, pDlg->m_bSplitByFileSize, pDlg->m_uFileSize)) { AfxMessageBox(TEXT("分割完成")); } else { AfxMessageBox(TEXT("分割失败")); } ::SendMessageW(pDlg->m_hWnd, WM_MYINFO, 1, 0); } else { ::SendMessageW(pDlg->m_hWnd, WM_MYINFO, 0, 0); if (pDlg->m_pMySplitAndMergeFile->Merge(pDlg->m_strFolderName, pDlg->m_strFileName, pDlg->m_strDestFileName)) { AfxMessageBox(TEXT("合并完成")); } else { AfxMessageBox(TEXT("合并失败")); } ::SendMessageW(pDlg->m_hWnd, WM_MYINFO, 1, 0); } return 0;}
阅读全文
1 0
- Windows Practice_文件_文件分割器(三)
- Windows Practice_文件_文件分割器(一)
- Windows Practice_文件_文件分割器(二)
- Windows Practice_文件搜索器(三)_线程池
- Windows Practice_文件搜索器(二)_多线程调试
- Windows Practice_文件_文件基础操作
- Windows Practice_文件_内存映射(一)
- Windows Practice_文件_注册表操作
- Windows Practice_文件搜索器(四)_封装文件扫描器
- Windows Practice_文件搜索器(一)递归
- Windows Practice_闹钟(三)_作业讲解和GDI概述
- Windows Practice_闹钟(一)_简易记事本
- Windows Practice_闹钟(二)_简易记事本
- Windows Practice_闹钟(六)_控件对象
- Windows Practice_内存映射_加载BMP
- (Java)文件分割器
- 文件分割器
- 文件分割器
- JAVA中this和super的用法
- Servlet实现文件下载
- 三十分钟熟悉es6(es6日常使用功能总结)
- 如何理解数据库事务中的一致性的概念?
- 欢迎使用CSDN-markdown编辑器
- Windows Practice_文件_文件分割器(三)
- javascript 红黑树算法与说明
- oracle数据库总结(一)
- mysql 相关自动化操作
- 建模总结
- World文档编写标准和方法总结
- 面试常见的排序
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛
- java.sql.SQLException: Access denied for user ''@'localhost' (using password: YES)