文件的合并与拆分

来源:互联网 发布:sql server findinset 编辑:程序博客网 时间:2024/06/01 09:10
最近编写了一个小工具,实现文件的合并与拆分,依然是使用的MFC,在编写工具过程中,基本把涉及到的文件与文件夹的操作都过了一遍,同时涉及到MFC中“Tab Contorl”“Combo Box”“List Box”以及"Check Box"的使用,对于一些常见的问题解决方法在这里做一个小小的总结。

Part 2:文件合并与拆分
选择文件
//用于存放文件名
CString fileName;
//文件过滤器(只显示我们想要格式的文件)
char* filters = _T("视频文件(*.txt)|*.txt");
//创建一个可以选择多个文件的CFileDialog
CFileDialog fileDlg(true,NULL,"*.txt",
OFN_ALLOWMULTISELECT | OFN_ENABLESIZING |
OFN_HIDEREADONLY,filters);
//最多可以打开50个文件
fileDlg.m_ofn.nMaxFile = 50 * MAX_PATH;
char* ch = new TCHAR[fileDlg.m_ofn.nMaxFile];
fileDlg.m_ofn.lpstrFile = ch;
//对内存块清零
ZeroMemory(fileDlg.m_ofn.lpstrFile,sizeof(TCHAR) * fileDlg.m_ofn.nMaxFile);
//打开文件对话框,用户选择之后,获得文件名集合
if(fileDlg.DoModal() == IDOK)
{
//获取第一个文件的位置
POSITION pos_file;
pos_file = fileDlg.GetStartPosition();
//读出每个路径并存放在数组中
while(pos_file != NULL)
{
//将文件路径增加至字符串末尾,以空格分隔,在这里也可以定义一个数组存放
fileName = fileDlg.GetNextPathName(pos_file);
fileName += " ";
m_filename.Add(fileName);
}
fileName=fileName.Left(fileName.GetLength()-1);//去掉最后一个空格
}
delete[] ch;
使用这种方式可以支持多文件的选择,下面还有一种简单的方法进行单个文件的选择。
//定义CString变量用于存放获取的文件名
CString fileName = _T("");
//创建一个CFileDialog
CFileDialog dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY,
_T("Describe Files (*.zv)|*.zv|All Files (*.*)|*.*||"), NULL);
//打开文件对话框,用户选择之后,获得文件名
if (dlgFile.DoModal())
{
fileName = dlgFile.GetPathName();
}
选择目录
char szPath[MAX_PATH]; //存放选择的目录路径
CString CatalogName;//定义字符串存放最终的目录
//内存块清零
ZeroMemory(szPath, sizeof(szPath));
//定义弹出的选择目录窗口
BROWSEINFO bi;
//进行初始化
bi.hwndOwner = m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = szPath;
bi.lpszTitle = "请选择文件目录:";
bi.ulFlags = 0;
bi.lpfn = NULL;
bi.lParam = 0;
bi.iImage = 0;
//弹出选择目录对话框
LPITEMIDLIST lp = SHBrowseForFolder(&bi);
if(lp && SHGetPathFromIDList(lp, szPath)) //将获取到的路径存放至szPath
{
//转换成CString格式的字符串
CatalogName.Format("%s",szPath);
}
以上2个功能是文件读写的前置操作,下面介绍正题。
文件合并
文件合并的流程是:
以读的方式打开N个老文件;
以写的方式打开新文件;(新,老文件打开顺序可变)
将读出的数据依次写到新文件末尾;
保存。
FILE * newfile, * oldfile;//定义“新”,“老”文件
CString fileName = "new.txt"; //默认打开的文件名
CString filter = "(*..txt)|*..txt||";//文件过虑的类型
//弹出保存文件对话框
CFileDialog openFileDlg(FALSE,"",fileName,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, filter, NULL);
if(openFileDlg.DoModal() == IDOK)
{
//获取用户填写的新文件名
CString check = openFileDlg.GetPathName();
//以“写”方式打开
newfile = fopen(check,"wb");
if( newfile == NULL)
{
AfxMessageBox("新文件创建失败");
}
//自己定义了一个文件列表,读取到每一个文件,依次写入
for (int i = 0;i<count;i++)
{
//文件名称临时变量
CString oldfilenametemp;
//获取文件名
m_myfilelist->GetText(i,oldfilenametemp);
//以“读”的方式打开
oldfile = fopen(oldfilenametemp,"rb");
//定义char型数组存放数据,MAXLEN是我自己定义的宏,长度为512*1024
unsigned char buf[MAXLEN];
//存放结果,如果读取文件成功,返回真正读取到的字节数
int rc;
//只要文件没有结束,一直读
while( (rc = fread(buf,sizeof(unsigned char), MAXLEN,oldfile)) != 0 )
{
//将读取的内容写到新文件的末尾
fwrite( buf, sizeof( unsigned char ), rc, newfile );
}
}
//关闭文件
fclose(oldfile);
fclose(newfile);
AfxMessageBox("合并成功");
文件拆分
文件拆分的流程是:
确定拆分出的文件大小;
打开一个老文件,读取内容;
每读到规定文件大小的内容就停止,保存为一个新文件,直到文件被全部读完;
//定义老文件
FILE * oldfile;
//定义文件长度
int oldfilelen = 0,newfilelen = 0;
//以“读”方式打开指定“oldfilepath”路径的文件
oldfile = fopen(oldfilepath,"rb");
fseek(oldfile,0,SEEK_END); //将源文件定位到文件尾
oldfilelen = ftell(oldfile); //获取文件长度
if(oldfile == NULL)
{
AfxMessageBox("文件打开失败");
}
// size为 XXX MB,转换成byte即为子文件长度
newfilelen = size*1048576;
//拆分得到的文件个数就是 “旧文件大小/新文件大小”
int num = ceil((double)(oldfilelen/newfilelen))+1;
for (int i = 0;i<num;i++)
{
FILE * newfile;//定义新文件
//以“写”方式打开指定“path”路径的文件(其实就是新文件的保存路径)
newfile = fopen(path,"wb");
//定义拆分文件长度的char型缓冲区
unsigned char * buf = new unsigned char[newfilelen];
//读取结果
int rc;
//从旧文件读出固定长度,存放到buf
oldfile = fopen(oldfilepath,"rb");
//设置偏移量
long offset = i * newfilelen;
//进行偏移
fseek(oldfile,offset,SEEK_SET);
rc = fread(buf,sizeof(unsigned char),newfilelen,oldfile);
//写入新文件中
fwrite( buf, sizeof( unsigned char ), rc, newfile );
//关闭新文件
fclose(newfile);
}
//拆分完成之后关闭老文件
fclose(oldfile);
AfxMessageBox("拆分成功");