使用C++Builder的内存流建立文件包

类别:编程语言 点击:0 评论:0 推荐:

 

   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