关键问题:

1.使用流的形式,读取原文件,写入到分割的子文件中

2.多个子文件使用从0开始的纯数字作为文件名,并在原文件所在路径下新建文件夹,保存子文件

3.子文件合并时,需要原文件的文件名与后缀,所以分割时,使用txt文件保存原文件的文件名与后缀

4.合并时,选择分割生成的文件夹下的任意文件,通过遍历读取该文件夹下的子文件还原文件

效果截图:

关键代码:

这里只放分割文件的处理代码与合并文件的处理代码:(部分变量需要联系到界面组件,不过也很好理解,可自行体会)

分割文件:

//点击“打开文件按钮”的响应函数
void CFileToolDlg::OnBnClickedButton1()
{TCHAR tszParam[200];CString strFileName;// 设置过滤器   ::_tcscpy_s(tszParam, sizeof(tszParam)/sizeof(TCHAR), _T("文件"));::_tcscat_s(tszParam, sizeof(tszParam)/sizeof(TCHAR), _T("|*.*||"));// 构造保存文件对话框 CFileDialog FileOpenDlg(TRUE, NULL, NULL, 0, tszParam);//文件对话框选择取消if (FileOpenDlg.DoModal() == IDCANCEL){return;}//获得对话框中输入文件的完整路径,同时包括文件名及扩展名(*.*)m_strPathName = FileOpenDlg.GetPathName();//获得文件名(*.*)m_strFileName = FileOpenDlg.GetFileName();//获得扩展名m_strFileExt = FileOpenDlg.GetFileExt();//获得文件名m_strFileTitle = FileOpenDlg.GetFileTitle();// 编辑框显示路径GetDlgItem(IDC_EDIT1)->SetWindowText(FileOpenDlg.GetPathName());
}//点击OK的响应函数
void CFileToolDlg::OnBnClickedOk()
{// 将各控件中的数据保存到相应的变量   ,自动调用DoDataExchangeUpdateData(TRUE);//创建线程处理文件OE_CreateThread(OE_NULL, &FileThread, (OE_VOID *)this);
}//文件处理线程函数
OE_VOID CFileToolDlg::FileThread(OE_VOID *lpParam)
{CFileToolDlg *pObj = (CFileToolDlg *)lpParam;pObj->FileFunc();
}//获取文件长度
LL GetFileLength( string& filepath)
{LL len = -1;ifstream in;in.open(filepath, ios_base::in);if (in.is_open()){in.seekg(0, ios::end);//对输入文件定位,它有两个参数:第一个参数是偏移量,第二个参数是基地址len = in.tellg();//它返回当前定位指针的位置,也代表着输入流的大小in.close();}return len;
}//创建文件目录,处理文件目录已存在的异常情况
void mkdir(string& path)
{int i = 1;while (access(path.c_str(), 0)!=-1)//文件目录存在,改名{path = path.substr(0, path.find_last_of('(')) + "(" + to_string(i) + ")";i++;}string s = "mkdir " + path;system(s.c_str());
}//处理文件的函数
OE_VOID CFileToolDlg::FileFunc()
{string message;//状态信息if (m_strPathName.GetLength()==0){//设置状态消息SetDlgItemText(IDC_STATIC,"还未选择任何文件,请重试!");return;}//获取用户选择的分割文件的大小CString cstrChoosed;//选择分割文件的大小m_combox.GetLBText(m_combox.GetCurSel(), cstrChoosed);double fSize;//大小选择的float类型string strChoosed = CT2A(cstrChoosed.GetBuffer());stringstream ss(strChoosed);ss >> fSize;LL llBlockSize = (long long)(fSize*1024*1024*1024);//GB->MB->KB->B//创建文件夹string strFilepath = CT2A(m_strPathName.GetBuffer());string strDir = strFilepath.substr(0, strFilepath.find_last_of('\\'))+"\\split";//拿到当前文件所在的路径,并创建子文件夹string strDirTitle = CT2A(m_strFileTitle.GetBuffer());strDir = strDir + "_" + strDirTitle;mkdir(strDir);//保存原文件名与后缀FILE* pStream;string strFileNamePath = strDir + "\\filename.txt";if ((pStream = fopen(strFileNamePath.c_str(), "w")) == NULL){AfxMessageBox(_T("打开文件失败!"));return;}if (fputs(CT2A(m_strFileName.GetBuffer()), pStream)!=0)//写入文件发生错误{SetDlgItemText(IDC_STATIC, _T("保存文件名失败,请重试!"));fclose(pStream);return;}fclose(pStream);//获取原文件大小string strOriFilepath = CT2A(m_strPathName.GetBuffer());LL llOriSize = GetFileLength(strOriFilepath);if (llOriSize == -1){SetDlgItemText(IDC_STATIC, _T("获取源文件大小失败!"));return;}//二进制方式读取原文件ifstream in;in.open(strOriFilepath, ios_base::in | ios_base::binary);if (!in.is_open()){SetDlgItemText(IDC_STATIC, _T("ifstream open failed"));return;}//分割文件char *buff = (char*)malloc(1024*1024*10);//读取缓冲大小,10MBmemset(buff, 0, 1024 * 1024 * 10);LL llReadCount = 0;//已读取大小LL llCurCount = 0;//一次读取的文件大小for (int i = 0; llReadCount < llOriSize; ++i){//设置状态消息message = "开始分割文件(" + to_string(llReadCount) + "/" + to_string(llOriSize) + ")......";SetDlgItemText(IDC_STATIC, message.c_str());//二进制写入子文件LL thisTimesRead = 0;//子文件已读取读取大小string strDivFile = strDir + "\\" + to_string(i);//分割后子文件的文件名ofstream out;out.open(strDivFile, ios_base::out | ios_base::binary);//打开(新建)文件,二进制方式写入if (!out.is_open()){SetDlgItemText(IDC_STATIC, _T("打开子文件失败!"));free(buff);break;}while (thisTimesRead < llBlockSize && llReadCount < llOriSize)//读取完一个块,或者文件已读取完,停止循环{memset(buff, 0, 1024 * 1024 * 10);in.read(buff, 1024 * 1024 * 10);llCurCount = in.gcount();//本次读取的文件大小if (llCurCount <= 0)//读取失败{SetDlgItemText(IDC_STATIC, _T("读取原文件失败,请重试!"));in.close();out.close();free(buff);return;}llReadCount += llCurCount;//增加已读取文件thisTimesRead += llCurCount;//增加子文件读取大小if(!out.write(buff, llCurCount)){SetDlgItemText(IDC_STATIC, _T("写入子文件失败,请重试!"));in.close();out.close();free(buff);return;}//设置状态消息message = "开始分割文件(" + to_string(llReadCount) + "/" + to_string(llOriSize) + ")......";SetDlgItemText(IDC_STATIC, message.c_str());}out.close();//UpdateData(false);if (llReadCount == llOriSize){//设置状态消息message = "已完成";SetDlgItemText(IDC_STATIC, message.c_str());}}in.close();free(buff);
}//合并按钮,弹出新窗口,在新窗口中处理合并
void CFileToolDlg::OnClickedButton2()
{// TODO: 在此添加控件通知处理程序代码//m_pMergeDlg.Create(IDD_DIALOG1, this);MergeDlg m_pMergeDlg;m_pMergeDlg.DoModal();
}

合并文件:

//文件处理线程函数
OE_VOID MergeDlg::FileThread(OE_VOID* lpParam)
{MergeDlg* pObj = (MergeDlg*)lpParam;pObj->FileFunc();
}//判断path是否是一个文件夹
bool IsDir(const char* path)
{WIN32_FIND_DATAA fd;FindFirstFileA(path, &fd);//搜索一个文件或目录的名称相匹配的特定名称的目录if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)//文档值为FILE_ATTRIBUTE_ARCHIVE(32),文件夹值为FILE_ATTRIBUTE_DIRECTORY(16)return true;elsereturn false;
}//获取文件长度
LL GetFileLength(const string& filepath)
{LL len = -1;ifstream in;in.open(filepath, ios_base::in);if (in.is_open()){in.seekg(0, ios::end);len = in.tellg();in.close();}return len;
}//检查文件是否存在
void checkFile(string& path)
{int i = 1;while (access(path.c_str(), 0) != -1)//存在{path = path.substr(0, path.find_last_of('(')) + "(out" + to_string(i) + ")"+ path.substr(path.find_last_of('.'),path.length());i++;}
}//处理文件合并的函数
OE_VOID MergeDlg::FileFunc()
{string strMessage;//状态信息//判断文件是否有效if (m_strPathName.GetLength() == 0){//设置状态消息SetDlgItemText(IDC_STATIC1, "还未选择任何文件,请重试!");return;}string strDir = CT2A(m_strPathName.GetBuffer());string strDivDir = strDir.substr(0, strDir.find_last_of('\\'));if (!IsDir(strDivDir.c_str()))//判断文件是否是文件夹{SetDlgItemText(IDC_STATIC, _T("error path!"));return;}//取出原文件名与后缀,生成合并文件的文件名FILE* pStream;string fileNamePath = strDivDir + "\\filename.txt";char line[200];if ((pStream = fopen(fileNamePath.c_str(), "r")) != NULL){if (fscanf_s(pStream, "%s", line, 200) == -1){SetDlgItemText(IDC_STATIC1, "读取原文件名失败,请重试!");fclose(pStream);return;}fclose(pStream);}else{AfxMessageBox(_T("打开文件失败,可能是您选择的文件不是子文件,请重试!"));return;}string strFileName(line);string strOutFile = strDivDir.substr(0, strDivDir.find_last_of('\\'))+"\\" + strFileName.substr(0, strFileName.find_last_of('.'))+"(out)"+ strFileName.substr(strFileName.find_last_of('.'), strFileName.length());//合并后的输出文件名checkFile(strOutFile);//判断文件名是否存在,存在则改名//二进制方式写入新文件ofstream out;out.open(strOutFile, ios_base::binary | ios_base::out);if (!out.is_open()){SetDlgItemText(IDC_STATIC, _T("can not create merge.out!"));return;}strDivDir += "\\";char* buffer = (char*)malloc(1024 * 1024 * 10);//读取缓冲LL llReadSize = 0;int i = 0;//循环次数即文件名while (1){//设置状态消息strMessage = "正在读取文件("+to_string(i)+")......";SetDlgItemText(IDC_STATIC1, strMessage.c_str());//二进制方式读取子文件LL llCurlen = GetFileLength(strDivDir + to_string(i));//获取当前i子文件大小LL thisTimesRead = 0;//当前子文件已读取大小ifstream in;in.open(strDivDir + to_string(i), ios_base::binary | ios_base::in);if (!in.is_open())//文件不存在时退出循环break;while (thisTimesRead < llCurlen)//直到子文件读取完{memset(buffer, 0, 1024 * 1024 * 10);in.read(buffer, 1024 * 1024 * 10);int cur_count = in.gcount();//本次读取大小if (cur_count <= 0)//读取失败{SetDlgItemText(IDC_STATIC1, _T("读取子文件失败,请重试!"));in.close();out.close();free(buffer);return;}thisTimesRead += cur_count;//子文件已读取大小llReadSize += cur_count;//输出文件大小if (!out.write(buffer, cur_count)){SetDlgItemText(IDC_STATIC1, _T("写入新文件失败,请重试!"));in.close();out.close();free(buffer);return;}//设置状态消息strMessage = "合并中(已读取" + to_string(llReadSize) + "B)......";SetDlgItemText(IDC_STATIC1, strMessage.c_str());}in.close();++i;}out.close();//设置状态消息strMessage = "已完成";SetDlgItemText(IDC_STATIC1, strMessage.c_str());free(buffer);
}//选择合并子文件按钮
void MergeDlg::OnClickedButton1()
{// TODO: 在此添加控件通知处理程序代码TCHAR tszParam[200];CString strFileName;// 设置过滤器   ::_tcscpy_s(tszParam, sizeof(tszParam) / sizeof(TCHAR), _T("文件"));::_tcscat_s(tszParam, sizeof(tszParam) / sizeof(TCHAR), _T("|*.*||"));// 构造保存文件对话框 CFileDialog FileOpenDlg(TRUE, NULL, NULL, 0, tszParam);//文件对话框选择取消if (FileOpenDlg.DoModal() == IDCANCEL){return;}//获得对话框中输入文件的完整路径,同时包括文件名及扩展名(*.*)m_strPathName = FileOpenDlg.GetPathName();//获得文件名(*.*)m_strFileName = FileOpenDlg.GetFileName();//获得扩展名m_strFileExt = FileOpenDlg.GetFileExt();//获得文件名m_strFileTitle = FileOpenDlg.GetFileTitle();// 编辑框显示路径GetDlgItem(IDC_EDIT1)->SetWindowText(FileOpenDlg.GetPathName());
}void MergeDlg::OnClose()
{//CDialogEx::OnClose();DestroyWindow();
}void MergeDlg::OnClickedButton2()
{// TODO: 在此添加控件通知处理程序代码//创建线程处理文件OE_CreateThread(OE_NULL, &FileThread, (OE_VOID*)this);
}

注释比较详细,完整代码就不放了。

MFC界面——实现分割与合并文件相关推荐

  1. Linux下分割与合并文件的方法

    Linux下分割与合并文件的方法 切割合并文件在linux下用split和cat就可以完成.下面举些实例进行说明. 1.文件切割 文件切割模式分为两种: 文本文件 二进制模式. 1.1文本模式 文本模 ...

  2. Linux 分割、合并文件

    分割 split命令. 将文件分隔成每个500M,且分割后的文件名以catalina.out开头.以2位数字结尾. split -d -a 2 -b 500m catalina.out catalin ...

  3. 关于 Delphi 中流的使用(9) 分割与合并文件的函数

    ====================================================== 注:本文源代码点此下载 ================================= ...

  4. java 输入流可以合并吗_Java 使用IO流实现大文件的分割与合并实例详解

    java 使用IO流实现大文件的分割与合并 文件分割应该算一个比较实用的功能,举例子说明吧比如说:你有一个3G的文件要从一台电脑Copy到另一台电脑, 但是你的存储设备(比如SD卡)只有1G ,这个时 ...

  5. 基于C++实现(MFC界面)家谱管理系统【100010005】

    概述 题目的理解和分析: 该程序带有MFC界面,有树形控件来展示家庭成员的层次关系,还有list控件来浏览家庭成员信息.以及有对家谱成员的添加,删除,修改,查询功能,统计男女比例和求平均年龄,以及有对 ...

  6. 超级文件分割《合并》机(分割大文件)

    需求:现在文件的大小越来越大,很多移动设备无法一次把文件一次全部拷贝完全,这种情况就需要把文件分割小点,分几次传送,然后,合并起来,这样就实现了大文件的拷贝功能 介绍:我的这个用的是吧文件分割成1M大 ...

  7. c语言文件分割与合并程序详解,如何实现将一个文件分割成多个小文件

    你也许会遇到到这样一个问题?当你有一个较大的软件,而无法用一张软盘将其全部拷下时,你也许会想到该将它分解开,分盘拷回去后,再将它们合并起来.现在的这种分割工具很多,你想自己动手做一个适合自己的分割工具 ...

  8. liunx 分割合并文件

    一 dd的作用是转换和拷贝文件,我们可以利用它来分割文件,相关的选项如下: if=filename:输入的文件名 of=finename:输出的文件名 bs=bytes:一次读写的字节数,默认是512 ...

  9. 使用python实现大文件分割与合并

    在平常的生活中,我们会遇到下面这样的情况: 你下载了一个比较大型的游戏(假设有10G),现在想跟你的同学一起玩,你需要把这个游戏拷贝给他. 然后现在有一个问题是文件太大(我们不考虑你有移动硬盘什么的情 ...

最新文章

  1. 高并发大型网站架构设计
  2. 详解医学顶刊《柳叶刀》最新发表新型冠状病毒研究论文
  3. wds和dhcp分开做需要注意问题
  4. faster rcnn resnet_Faster-rcnn 代码详解
  5. mysql安装时1045错误_MySql 安装时的1045错误
  6. 安装mysql5.7,如何将之前mysql的数据库导入
  7. 通过反射访问private的属性或方法
  8. 移动端图片裁剪上传—jQuery.cropper.js
  9. vector java 复制_孙悟空的身外身法术使用了Java设计模式:原型模式
  10. spring mvc+mybatis ios android整合cms内容发布平台
  11. clickhouse 同步mysql_ClickHouse 常用管理命令
  12. Win10鼠标宏怎么设置?电脑设置鼠标宏的方法
  13. Java自动化测试系列[v1.0.1][PO设计模式]
  14. HTML:使用JavaScript(js)脚本在网页上显示实时时间
  15. Max Script|控制器-位置约束_path
  16. depot_tools下载
  17. 前端工程师考核总结_web前端年度工作总结
  18. python多条件求和_数据的多条件求和
  19. [敏捷开发培训] Scrum 和 Kanban
  20. 涉密计算机不得接入 网络,任何组织和个人都不得将涉密计算机、涉密存储设备接入互联网或其他公共信息网络 - 作业在线问答...

热门文章

  1. 妈妈也曾是少女!Binking玫瑰海藻银耳羹,还妈妈一个粉红的梦!
  2. 什么是.NET的程序集?
  3. 几个免费好用的IP查询接口
  4. 《三国演义》之人物出场统计
  5. CentOS 7使用ttyd搭建一个WEB共享终端(WebSSH)
  6. Sign签名生成与校验
  7. excel 获取股票价格_股票价格的Excel点图
  8. 又一家美业SaaS+系统宣布停止服务,美业人你怎么看?
  9. 自然语言处理之语言模型与词向量
  10. 网页生成pdf文件。(html转pdf)(带效果图)