📄 filecutmerge.cpp
字号:
//---------------------------------------------------------------------------
//功能:
//用于实现文件的分割和合并
//利用构造函数在新建对象前就创建一个文件包流
//
//说明:
//1.将包含其他文件内容的文件称为Package(包);
//2.包的数据结构如下:
// 文件总数--第一个文件信息包--第二个文件信息包--...第一个文件内容--...
//3.新包的文件总数为0
//4.有两个初始化构造函数,一个指明了包文件名,另一个没有,初始化失败时
// pPackage为NULL;
//5.在文件中用到的包流对象仅包含文件本身的内容,文件头对象是另外单独管理
// 的,仅在保存包文件时将文件头对象写入包文件中
//6.在析构函数中将包流写入文件.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "FileCutMerge.h"
__fastcall FileCutMerge::FileCutMerge(String PackageFileName,bool NeedCreate,TComponent* AOwner):TComponent(AOwner)
{
if(OpenPackage(PackageFileName,NeedCreate)==false)
throw String("您指定了另外一种格式的文档,或者文档已损坏,不能打开它") ;
}
//---------------------------------------------------------------------------
__fastcall FileCutMerge::~FileCutMerge()
{
SavePackageToDisk();
}
//---------------------------------------------------------------------------
bool __fastcall FileCutMerge::AddFile( String FileName)
{
//向指定的流pPackage增加单个文件FileName,成功返回True
//打开的文件不管是否拆分过,一律等同对待
//前提:
//要求FileName文件必须存在
//打开文件
TFileStream *pNewFile=pStreamOpt->OpenFileStream(FileName,"ReadWrite");
if(pPackage==NULL)
return false;
//将流加入到包中
bool ret=pStreamOpt->AppendStream(pPackage,pNewFile);
//加入失败
if(ret==false)
return false;
//创建文件信息对象,未指定的对象保持缺省值
pInfo=new FileInfo(this);
pInfo->FileName=ExtractFileName(FileName);
pInfo->FilePath =ExtractFilePath(FileName);
pInfo->FileSize =pNewFile->Size;
//将文件信息对象放入容器中
pVector->push_back(pInfo);
//删除文件流
pNewFile->Free();
//增加文件总数
FileNum++;
return true;
}
#pragma package(smart_init)
int __fastcall FileCutMerge::GetFileNum()
{
//得到文件包中文件的个数
return FileNum;
}
FileInfo * __fastcall FileCutMerge::GetFileInfo(unsigned int num)
{
//向外界中返回容器中指定序号的文件信息对象指针,失败返回NULL
if(num>=pVector->size())
return NULL;
return pVector->at(num);
}
int __fastcall FileCutMerge::GetFileOffset(unsigned int num)
{
//获取指定序号(从0起)文件在流中的起始点,-1表示出错
int Offset=0;
if(num>=pVector->size())
return -1;
for(unsigned int i=0;i<num;i++)
Offset+=(pVector->at(i))->FileSize;
return Offset;
}
bool __fastcall FileCutMerge::ExtractFile(unsigned int num,String path,bool OverCover)
{
//从完整的文件包中解开单个文件,成功返回True
//OverCover参数用于决定是否覆盖同名文件,num用于指明文件头对象在容器中的序号
//
//前提:
//1.要求Path必须存在,如果不存在,则强制创建它
if(DirectoryExists(path)==false)
ForceDirectories(path);
if(num>=pVector->size())
return false;
int offset;
offset=GetFileOffset(num);
bool ret=pStreamOpt->ExtractStream(pPackage,path+"\\"+(pVector->at(num))->FileName,offset,(pVector->at(num))->FileSize,OverCover);
return ret;
}
bool __fastcall FileCutMerge::ExtractAllFiles(String path,bool OverCover)
{
//解压全部文件,成功返回True
int i;
for(i=0;i<FileNum;i++)
ExtractFile(i,path,OverCover);
return true;
}
bool __fastcall FileCutMerge::DeleteAFile(unsigned int no)
{
//删除指定序号的文件
//
//前提:
//no必须是有效的序号
if(no>=pVector->size())
return false;
FileInfo *p=pVector->at(no);
//获取偏移量
int begin=GetFileOffset(no);
//删除文件流
bool ret=pStreamOpt->CutOutStream(pPackage,begin,p->FileSize);
if(ret) //从容器中删除指定FileInfo对象
{
pVector->erase(pVector->begin()+no);
//文件数减一
FileNum--;
}
return ret;
}
bool __fastcall FileCutMerge::SplitFile(String FileName,String Path, int size)
{
//将文件包按单个分割尺寸进行分割,成功返回True。
//文件名格式为:FileName.jxl_0~FileName.jxl_1....
//
//前提:
//分割包文件名必须是新的,不允许有同名文件,有则覆盖.
//
//说明:
//为获取完整的文件包,先将包存盘;
try
{
//将当前文件包保存到磁盘中,这是为了能将更改过的文件头保存到文件中
SavePackageToDisk();
//获取一份文件内容的流
TFileStream* pTempPackage=pStreamOpt->OpenFileStream(PkgFileName,"Read");
if(pTempPackage==NULL)
return false;
if(pTempPackage->Size<size)
return false;
//计算切割的文件数
int MergeTotalNum=(pTempPackage->Size/size)+1;
//生成单个文件,除了最后一个文件
for(int i=0;i<MergeTotalNum-1;i++)
{
//创建新文件流
TFileStream *ptempFile;
ptempFile=pStreamOpt->OpenFileStream(Path+"\\"+FileName+".jxl_"+IntToStr(i),"CreateWrite");
if(ptempFile==NULL)
return false;
//生成文件信息对象
FileInfo *ptempInfo=new FileInfo(this);
ptempInfo->FileName =Path+FileName+".jxl_"+IntToStr(i);
ptempInfo->FilePath =Path;
ptempInfo->FileSize =size;
ptempInfo->NeedMerge =true;
ptempInfo->MergeTotalNum=MergeTotalNum ;
ptempInfo->MergeNo =i;
//写入文件信息对象个数
int j=1;
ptempFile->Write(&j,sizeof(int));
//写入文件信息对象
ptempFile->WriteComponent(ptempInfo);
//写入文件流本身内容
pTempPackage->Seek(i*size,soFromBeginning);
ptempFile->CopyFrom(pTempPackage,size);
ptempFile->Free();
delete ptempInfo;
}
//写入最后一个文件
TFileStream *ptempFile=pStreamOpt->OpenFileStream(Path+"\\"+FileName+".jxl_"+IntToStr(MergeTotalNum-1),"CreateWrite");
if(ptempFile==NULL)
return false;
//生成文件信息对象
FileInfo *ptempInfo=new FileInfo(this);
ptempInfo->FileName =Path+"\\"+FileName+".jxl_"+IntToStr(MergeTotalNum-1);
ptempInfo->FilePath =Path;
ptempInfo->FileSize =pTempPackage->Size % size; //取余,得出最后一个文件的长度
ptempInfo->NeedMerge =true;
ptempInfo->MergeTotalNum=MergeTotalNum ;
ptempInfo->MergeNo =MergeTotalNum-1;
//写入文件信息对象个数
int j=1;
ptempFile->Write(&j,sizeof(int));
//写入文件信息对象
ptempFile->WriteComponent(ptempInfo);
//写入文件流本身内容
pTempPackage->Seek((MergeTotalNum-1)*size,soFromBeginning);
ptempFile->CopyFrom(pTempPackage,ptempInfo->FileSize);
ptempFile->Free();
pTempPackage->Free();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -