⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filecutmerge.cpp

📁 适合初学者学习以及程序员回顾
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------
//功能:
//用于实现文件的分割和合并
//利用构造函数在新建对象前就创建一个文件包流
//
//说明:
//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 + -