source:
//All right revsered by yoki2009
//mailto:imj040144@tom.com
//微出版 www.epube.biz 相信梦想无界
#include <cctype>
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <map>
#include "DefException.h"
using namespace std;
#define BUF_SIZ 8096
namespace FILESPLIT
{
static int cnt = 0;
int initConfig()
{
WritePrivateProfileString("Config","ID",
"0","./docid.pos");
return TRUE;
}
map<int , string> filelist;
static int fileid = 1;
int splitGreatToSlice(const string &srcName)
{
filelist[fileid] = srcName;
fileid++;
ifstream infile(srcName.c_str(),ios_base::binary);
if (!infile)
{
throw err::RunException("Open File Error.");
return FALSE;
}
bool isEnd = FALSE;
//check if it is the first time to splite the file
char recordID[16];
GetPrivateProfileString("Config","ID","0",recordID,16,"./docid.pos");
char bstartFile[64];
char bendpos[4];
if (!strcmp(recordID,"0"))
{
cnt = 0;
}else
{
cnt = atoi(recordID);
GetPrivateProfileString("Config","LastFile","",
bstartFile,64,"./docid.pos");
GetPrivateProfileString("Config","LastFilePos","0",
bendpos,4,"./docid.pos");
}
ostringstream oss;
oss<<"tmp."<<cnt;
WritePrivateProfileString(srcName.c_str(),"StartFile",
oss.str().c_str(),"./docid.pos");
while(!isEnd)
{
oss.str("");
oss<<"tmp."<<cnt;
cnt++;
ofstream outfile(oss.str().c_str(),ios_base::binary|ios_base::app);
if (!outfile)
{
throw err::RunException("Create tmp File Error.");
return FALSE;
}
for (size_t i=0;i<BUF_SIZ;i+=infile.gcount())
{
char buf[BUF_SIZ];
//read content from new file
//Fill the content when there is also have space in the last file
if (0 != atoi(bendpos))
{
if (infile.read(buf,(BUF_SIZ - atoi(bendpos))))
{
outfile.write(buf,(BUF_SIZ - atoi(bendpos)));
strcpy(bendpos,"0");
break;
}
}
if (infile.read(buf,BUF_SIZ))
{
outfile.write(buf,BUF_SIZ);
}else
{
//buf[infile.gcount()]='/0';
outfile.write(buf,infile.gcount());
isEnd = TRUE;
//record FILE start and end pos.
//ostringstream startpos;
ostringstream endpos;
//startpos<<;
endpos<<infile.gcount();
WritePrivateProfileString(srcName.c_str(),"EndFile",
oss.str().c_str(),"./docid.pos");
WritePrivateProfileString(srcName.c_str(),oss.str().c_str(),
endpos.str().c_str(),"./docid.pos");
//record last file information.
WritePrivateProfileString("Config","LastFile",
oss.str().c_str(),"./docid.pos");
WritePrivateProfileString("Config","LastFilePos",
endpos.str().c_str(),"./docid.pos");
//To save one variable,use endpos to store cnt.
endpos.str("");
endpos<<(--cnt);
WritePrivateProfileString("Config","ID",endpos.str().c_str(),"./docid.pos");
outfile.close();
break;
}
outfile.close();
}
}
infile.close();
return TRUE;
}
int mergeSliceToNormal(const string &srcName)
{
SetCurrentDirectory("./");
ostringstream newFile;
newFile<<srcName.c_str()<<".new";
ofstream outfile(newFile.str().c_str(),ios_base::binary);
char startFile[64];
char endFile[64];
char endpos[4];
char currentendpos[8];
bool firstVisit = FALSE;
GetPrivateProfileString(srcName.c_str(),"StartFile","",startFile,64,"./docid.pos");
GetPrivateProfileString(srcName.c_str(),"EndFile","",endFile,64,"./docid.pos");
char tmpEndFile[64];
GetPrivateProfileString((filelist[filelist.size()-1]).c_str(),"EndFile","",tmpEndFile,64,"./docid.pos");
GetPrivateProfileString((filelist[filelist.size()-1]).c_str(),tmpEndFile,"",endpos,4,"./docid.pos");
if (!strcmp(startFile,"tmp.0"))
{
firstVisit = TRUE;
}
char tmp[] = "tmp.";
char *startFilePos = NULL;
char *endFilePos = NULL;
startFilePos = strtok(startFile,tmp);
endFilePos = strtok(endFile,tmp);
for (int i = atoi(startFilePos);i<=atoi(endFilePos);i++)
{
ostringstream oss;
char buf[BUF_SIZ];
oss<<"tmp."<<i;
ifstream infile(oss.str().c_str(),ios_base::binary);
//if it was the first visit,you should seek the the begin pos in
// the last file.
if (!firstVisit)
{
infile.seekg(atoi(endpos));
firstVisit = TRUE;
if (infile.read(buf,(BUF_SIZ - atoi(endpos))))
{
outfile.write(buf,(BUF_SIZ - atoi(endpos)));
}else
{
outfile.write(buf,infile.gcount());
}
continue;
}
//if reach the last file, you should only read the length of buf
//which belonged this file.
if (i == atoi(endFilePos))
{
GetPrivateProfileString(srcName.c_str(),oss.str().c_str
(),"",currentendpos,8,"./docid.pos");
if (infile.read(buf,atoi(currentendpos)))
outfile.write(buf,atoi(currentendpos));
break;
}
if (infile.read(buf,BUF_SIZ))
{
outfile.write(buf,BUF_SIZ);
}else
{
outfile.write(buf,infile.gcount());
}
infile.close();
}
outfile.close();
return TRUE;
}
}
Testing:
FILESPLIT::initConfig();
FILESPLIT::splitGreatToSlice("c://vs//first.exe");
FILESPLIT::splitGreatToSlice("c://vs//second.exe");
FILESPLIT::mergeSliceToNormal("c://vs//first.exe");
FILESPLIT::mergeSliceToNormal("c://vs//second.exe");