C++Builder为我们提供了很多的有用的组件,这就不用我多说了,我写这篇文章是因为我刚给我们实验室做完了一个数据库的程序,其中有一部分产品数据管理(PDM),要将每一张PRO/E工程图存放到数据库中的一个字段中,数据库用的是SQLSever。我想有必要解释一下PRO/E工程图的组成,PRO/E在我们机械行业中是大名鼎鼎三维建模软件,一个PRO/E工程图文件由多个后缀为PRT和后缀为ASM的文件组成,也就是说要将一个PRO/E工程图文件存入数据库一个字段中必须将所有文件打包后存入,当然,从数据库中取出后就要拆包然后存到硬盘文件夹下,数据库中的表就是这个样子:
存储装配图时,使用文件流操作将一张Pro/E装配图的多个文件合并为一个文件包,然后将该文件包存入数据库中的一个字段中。在客户端显示时,将数据库中的装配图文件包拆包后下载到客户端某一文件夹下,然后在程序中显示。关键技术是文件的打包与拆包,我的办法是封装一个文件包进行该操作,该文件包的形式如下:
MemoryHeader
FileHeader1
文件1内容
FileHeader2
文件2内容
FileHeader3
在该文件包中,有两种头结构分别为MemoryHeader和FileHeader,在程序中他们被定义为两个结构,结构形式如下:
typedef struct MemoryHeader
{
int iFileCount;
} MemoryHeader, *PMemoryHeader;
typedef struct FileHeader
{
char FileName[50];
double long iSize;
} FileHeader,*PFileHeader;
MemoryHeader结构中只有一个int型的变量iFileCount,它用于记录在该文件中包中文件的个数。FileHeader头文件中有两个变量,FileName用于记录文件的名字,iSize用于记录文件的大小。这两个结构的长度分别为4和72字节,再利用FileHeader中所记录的文件的大小,就可以准确的确定每一个文件的大小和文件在文件包中的位置。
文件包实现类封装,该类的主要函数及其主要作用如下:
class FilePackage
{
private:
//私有成员,用于文件包在内存中的临时存储,在后续操作中,将该内存流所存储的//文件包存于数据库或借包存于硬盘上
TMemoryStream * memData;
public:
//用于返回数据成员memData
TMemoryStream * c_mem();
//将文件名为str的文件加入到文件包中
bool LoadFromFile(AnsiString str);
//用于初始化该文件包
bool init();
//清除内存流中的数据
bool memClear();
//将数据成员memData指向外部内存流mem
bool CopyMem(TMemoryStream *mem);
//将文件包解包后存储全体文件到文件夹strSaveFolder下
bool SaveToFile(AnsiString strSaveFolder);
};
下面仅对函数LoadFromFile和SaveToFile作具体说明以便明确内存流的使用方法
LoadFromFile函数具体实现如下:
bool FilePackage::LoadFromFile(AnsiString str)
{
bool bSuccess;
bSuccess = true;
//声明一个临时内存流用于装载文件str并将该内存流读写位置设置为0
TMemoryStream * tempMem = new TMemoryStream();
tempMem->Position = 0;
//将文件内容加载到临时内存流中
tempMem->LoadFromFile(str);
//临时字符串用于获得文件名
AnsiString strTemp;
strTemp = ExtractFileName(str);
// FileHeader文件结构myHeader用于存储该文件名及大小
FileHeader myHeader;
StrCopy(myHeader.FileName,strTemp.c_str());
myHeader.iSize = tempMem->Size ;
//内存头文件markHeader用于获得文件包中的数量
MemoryHeader markHeader;
memData->Position = 0;
memData->ReadBuffer(&markHeader,sizeof(MemoryHeader));
//临时头文件用于确定该文件在内存包中的位置
FileHeader tmpFHeader;
for (int i=0;i<markHeader.iFileCount ;i++)
{
memData->ReadBuffer(&tmpFHeader,sizeof(FileHeader));
memData->Position += tmpFHeader.iSize ;
}
//将该文件的名字及内容写入文件包
memData->WriteBuffer(&myHeader,sizeof(myHeader));
tempMem->Position = 0;
memData->CopyFrom(tempMem,tempMem->Size);
//将总文件数量加一后写入文件包中
markHeader.iFileCount += 1;
memData->Position = 0;
memData->WriteBuffer(&markHeader,sizeof(MemoryHeader));
//释放临时内存流
tempMem->Free();
return bSuccess;
}
SaveToFile的函数说明如下:
bool FilePackage::SaveToFile(AnsiString strSaveFolder)
{
bool bFlag;
bFlag = true;
//如果该内存包小于76则提示没有文件
if (this->memData->Size < 76)
{
ShowMessage("这个包里没文件!!");
return bFlag;
}
// memTemp存放从包中解出的单个文件
TMemoryStream * memTemp = new TMemoryStream();
MemoryHeader theHeader;
FileHeader tmpFHeader;
memData->Position = 0;
try
{
memData->ReadBuffer(&theHeader,sizeof(theHeader));
//读取包中的每个文件并保存到硬盘文件夹下
for (int i=0;i<theHeader.iFileCount ;i++)
{
memData->ReadBuffer(&tmpFHeader,sizeof(FileHeader));
memTemp->Position = 0;
memTemp->CopyFrom(memData,tmpFHeader.iSize);
memTemp->Position = 0;
memTemp->SaveToFile(strSaveFolder + "\\" + tmpFHeader.FileName);
}
}
catch(...)
{
bFlag = false;
}
memTemp->Free();
return bFlag;
}
最后把全部源码贴上,有兴趣地看看吧
//////////////////
wxfMemoryStream.h
///////////////////////////////////
typedef struct MemoryHeader
{
int iFileCount;
} MemoryHeader, *PMemoryHeader;
typedef struct FileHeader
{
char FileName[50];
double long iSize;
} FileHeader,*PFileHeader;
class wxfFilePackage
{
private:
TMemoryStream * memData;
public:
wxfFilePackage();
~wxfFilePackage();
void ShowHello();
TMemoryStream * c_mem();
bool LoadFromFile(AnsiString str);
bool init();
bool memClear();
bool CopyMem(TMemoryStream *mem);
bool SaveToFile(AnsiString strSaveFolder);
};
/////////////////////////////////
wxfMemoryStream.cpp
///////////////////////////////////
wxfFilePackage::~wxfFilePackage()
{
memData->Free();
}
//---------------------------------------------------------------------------
wxfFilePackage::wxfFilePackage()
{
memData = new TMemoryStream();
MemoryHeader memHeader;
memHeader.iFileCount = 0;
memData->WriteBuffer(&memHeader,sizeof(memHeader));
}
//---------------------------------------------------------------------------
bool wxfFilePackage::CopyMem(TMemoryStream * mem)
{
bool bFlag = true;
this->memData = mem;
return bFlag;
}
bool wxfFilePackage::init()
{
bool bFlag;
bFlag = true;
try
{
MemoryHeader memHeader;
memHeader.iFileCount = 0;
memData->WriteBuffer(&memHeader,sizeof(memHeader));
}
catch(...)
{
bFlag = false;
}
return bFlag;
}
//---------------------------------------------------------------------------
bool wxfFilePackage::memClear()
{
bool bFlag;
bFlag = true;
try
{
this->memData->Clear();
}
catch(...)
{
bFlag = false;
}
return bFlag;
}
//---------------------------------------------------------------------------
void wxfFilePackage::ShowHello()
{
AnsiString strS;
strS = "Hello world";
ShowMessage(strS);
}
//---------------------------------------------------------------------------
TMemoryStream * wxfFilePackage::c_mem()
{
return memData;
}
//---------------------------------------------------------------------------
bool wxfFilePackage::LoadFromFile(AnsiString str)
{
bool bSuccess;
bSuccess = true;
////test
//int k = memData->Size ;
//init tempMem and fill it with file
TMemoryStream * tempMem = new TMemoryStream();
tempMem->Position = 0;
tempMem->LoadFromFile(str);
AnsiString strTemp;
strTemp = ExtractFileName(str);
FileHeader myHeader;
StrCopy(myHeader.FileName,strTemp.c_str());
myHeader.iSize = tempMem->Size ;
MemoryHeader markHeader;
memData->Position = 0;
memData->ReadBuffer(&markHeader,sizeof(MemoryHeader));
FileHeader tmpFHeader;
//locate the position where the new file should be insert
for (int i=0;i<markHeader.iFileCount ;i++)
{
memData->ReadBuffer(&tmpFHeader,sizeof(FileHeader));
memData->Position += tmpFHeader.iSize ;
}
//write header and file
memData->WriteBuffer(&myHeader,sizeof(myHeader));
tempMem->Position = 0;
memData->CopyFrom(tempMem,tempMem->Size);
//write increacement
markHeader.iFileCount += 1;
memData->Position = 0;
memData->WriteBuffer(&markHeader,sizeof(MemoryHeader));
/////test
//memData->Position = 0;
//MemoryHeader testmem;
//memData->ReadBuffer(&testmem,sizeof(MemoryHeader));
//int i = testmem.iFileCount ;
//delete tempMem
tempMem->Free();
return bSuccess;
}
//---------------------------------------------------------------------------
bool wxfFilePackage::SaveToFile(AnsiString strSaveFolder)
{
bool bFlag;
bFlag = true;
if (this->memData->Size < 76)
{
ShowMessage("这个包里没文件!!");
return bFlag;
}
///存放从包中解出的单个文件
TMemoryStream * memTemp = new TMemoryStream();
MemoryHeader theHeader;
FileHeader tmpFHeader;
memData->Position = 0;
try
{
memData->ReadBuffer(&theHeader,sizeof(theHeader));
for (int i=0;i<theHeader.iFileCount ;i++)
{
memData->ReadBuffer(&tmpFHeader,sizeof(FileHeader));
memTemp->Position = 0;
memTemp->CopyFrom(memData,tmpFHeader.iSize);
memTemp->Position = 0;
memTemp->SaveToFile(strSaveFolder + "\\" + tmpFHeader.FileName);
}
}
catch(...)
{
bFlag = false;
}
memTemp->Free();
return bFlag;
}
本文地址:http://com.8s8s.com/it/it24960.htm