1. //测试通过 科嵌电子  
  2.  
  3. #include <stdio.h>   
  4. #include <string.h>   
  5. #include <stdlib.h>   
  6.    
  7. typedef unsigned int  uint;   
  8. typedef unsigned char byte;              
  9.    
  10. // 包文件中最大可容纳的文件个数   
  11. #define MAX_FILE_COUNT 10   
  12.    
  13. // 全局包文件指针   
  14. FILE*  g_pMasFile = NULL;   
  15.  
  16. // 资源包文件头结构   
  17. typedef struct SMaseFileHeader   
  18. {   
  19.  uint  uFileFlag;         // 包文件头标记: 'MASE'   
  20.  uint  uFileCount;        // 包内文件个数   
  21.  uint  uFileListOfs;      // 文件列表偏移   
  22.  uint  uMaxFileCount;     // 最大子文件个数   
  23.  uint  uFileSize;         // 包文件的大小   
  24. }MaseHeader;   
  25.    
  26. // 包内文件信息结构   
  27. typedef struct SFilesMessage   
  28. {   
  29.  uint  uFileOfs;          // 本文件在包内的偏移   
  30.  uint  uFileSize;         // 本文件的大小   
  31.  char  szFileName[260];   // 本文件的路径   
  32. }FilesMsg;   
  33.  
  34. // 打开包文件   
  35. int OpenMasFile(const char* path, const byte onlyOpen)   
  36. {   
  37.  uint       uWriteCount;       // 写入文件信息次数   
  38.  byte       bIsNew = 0;        // 是否新建的   
  39.  MaseHeader header;            // 文件头结构定义   
  40.  FilesMsg   msg;               // 文件信息结构定义  
  41.  
  42.  g_pMasFile = fopen(path, "rb");  // 用来判断是否存在   
  43.  if (g_pMasFile == NULL)        
  44.  {   
  45.   if (onlyOpen == 1)            // 只打开不新建   
  46.    return -1;    
  47.    
  48.   bIsNew = 1;   
  49.   g_pMasFile = fopen(path, "wb");   
  50.   if (g_pMasFile == NULL)   
  51.    return -1;   
  52.  }   
  53.  
  54.  //先关闭,然后在用"rb+"方式打开  二进制读写打开文件  
  55.  fclose( g_pMasFile );   
  56.  
  57.  g_pMasFile = fopen(path, "rb+");   
  58.  if (g_pMasFile == NULL)   
  59.   return -1;   
  60.    
  61.  if(bIsNew == 1)// 新建的文件   
  62.  {   
  63.   header.uFileFlag     = 'ESAM';   
  64.   header.uFileCount    = 0;   
  65.   header.uFileListOfs  = sizeof(MaseHeader); //紧跟着就是文件列表   
  66.   header.uMaxFileCount = MAX_FILE_COUNT;   
  67.   header.uFileSize     = sizeof(MaseHeader)    
  68.           + (MAX_FILE_COUNT * sizeof(FilesMsg));   
  69.  
  70.   //写入头信息   
  71.   fwrite(&header, sizeof(MaseHeader), 1, g_pMasFile);   
  72.   memset(&msg, 0, sizeof(FilesMsg));   
  73.   uWriteCount = MAX_FILE_COUNT;   
  74.  
  75.   //写入文件列表用0占位   
  76.   while(uWriteCount--)   
  77.      fwrite(&msg, sizeof(FilesMsg), 1, g_pMasFile);   
  78.  }   
  79.  else//文件存在   
  80.  {   
  81.     //则读取头文件信息   
  82.     fread(&header, sizeof(MaseHeader), 1, g_pMasFile);   
  83.  }   
  84.  
  85.  //检查文件头标记   
  86.  if (header.uFileFlag != 'ESAM')   
  87.  {   
  88.   fclose(g_pMasFile);  
  89.   printf("文件头标记不对,错误!\n");  
  90.   return -1;   
  91.  }   
  92.    
  93.  //检查数据是否完整   
  94.  if (header.uMaxFileCount != MAX_FILE_COUNT)   
  95.  {   
  96.   fclose(g_pMasFile);   
  97.   printf("数据不完整,错误!\n");  
  98.      return -1;   
  99.  }   
  100.    
  101.  return 0;   
  102. }   
  103.    
  104. //写文件到包里   
  105. int WriteFileToPak(const char* path)   
  106. {   
  107.  FilesMsg   fileMsg;      //此文件的文件信息结构   
  108.  MaseHeader header;       //包文件头结构定义   
  109.  uint       uFileSize;   
  110.  uint       uFileListEndOfs;   
  111.  byte*      pBuff;   
  112.  FILE*      pFile = NULL;   
  113.    
  114.  if (g_pMasFile == NULL)   
  115.      return -1;   
  116.    
  117.  memset(&fileMsg, 0, sizeof(FilesMsg));   
  118.  fseek(g_pMasFile, 0, SEEK_SET);    //定位到文件头,读取头文件信息  
  119.    
  120.  //则读取头文件信息   
  121.  fread(&header,sizeof(MaseHeader), 1, g_pMasFile);   
  122.    
  123.  uFileListEndOfs = header.uFileCount * sizeof(FilesMsg) + header.uFileListOfs;   
  124.    
  125.  pFile = fopen(path, "rb");   
  126.  if(pFile == NULL)   
  127.      return -1;   
  128.    
  129.  fseek(pFile, 0, SEEK_END);   
  130.  uFileSize = ftell(pFile);   
  131.  fseek(pFile, 0, SEEK_SET);   
  132.    
  133.  //文件名长度不能超过260   
  134.  strcpy(fileMsg.szFileName,path);   
  135.  fileMsg.uFileOfs  = header.uFileSize;   
  136.  fileMsg.uFileSize = uFileSize;   
  137.    
  138.  // 写入文件信息   
  139.  // 将文件指针定位到uFileListEndOfs处,以便写入新的文件信息结构   
  140.  fseek(g_pMasFile, uFileListEndOfs, SEEK_SET);   
  141.  fwrite(&fileMsg,sizeof(FilesMsg),1,g_pMasFile);   
  142.    
  143.  // 申请空间   
  144.  pBuff = (byte*)malloc(uFileSize);   
  145.  fread(pBuff,uFileSize,1,pFile);   
  146.    
  147.  // 写数据到包文件里   
  148.  fseek(g_pMasFile,header.uFileSize,SEEK_SET);   
  149.  fwrite(pBuff, uFileSize, 1, g_pMasFile);   
  150.    
  151.  // 释放内存   
  152.  free(pBuff);   
  153.    
  154.  //重新填充header   
  155.  header.uFileCount += 1;   
  156.  header.uFileSize  += uFileSize;   
  157.    
  158.  fseek( g_pMasFile,0,SEEK_SET);   
  159.    
  160.  // 重新写入包文件头   
  161.  fwrite(&header,sizeof(MaseHeader),1,g_pMasFile);   
  162.    
  163.  return 0;   
  164. }   
  165.    
  166. //从包文件里读数据   
  167. int ReadFileFromPak(const FilesMsg msg, byte* _dst)   
  168. {   
  169.  if ( g_pMasFile == NULL )   
  170.      return -1;   
  171.    
  172.  fseek(g_pMasFile, msg.uFileOfs,SEEK_SET);   
  173.  fread(_dst, msg.uFileSize, 1, g_pMasFile);   
  174.    
  175.  return 0;   
  176. }   
  177.    
  178. //获取包中某个文件的信息   
  179. int GetFileMessage( const char* path, FilesMsg* msg)   
  180. {   
  181.  FilesMsg   fileMsg;      // 此文件的文件信息结构   
  182.  MaseHeader header;       // 包头结构   
  183.  uint       uFileCount;   // 文件个数   
  184.    
  185.  if ( g_pMasFile == NULL || msg == NULL )   
  186.      return -1;   
  187.    
  188.  // 则读取头文件信息   
  189.  fseek(g_pMasFile, 0, SEEK_SET);   
  190.  fread(&header, sizeof(MaseHeader), 1, g_pMasFile);   
  191.    
  192.  uFileCount = header.uFileCount;   
  193.  while (uFileCount--)   
  194.  {   
  195.      fread(&fileMsg, sizeof(FilesMsg), 1,g_pMasFile);   
  196.  
  197.      // 判断是否是要获取的文件   
  198.      if (stricmp(fileMsg.szFileName, path) == 0 )   
  199.      {               
  200.    *msg = fileMsg;   
  201.          return 0;   
  202.      }   
  203.  }   
  204.  return -1;   
  205. }   
  206.    
  207. // 关闭包文件   
  208. int CloseMasFile( void )   
  209. {   
  210.  if ( g_pMasFile == NULL )   
  211.      return -1;   
  212.    
  213.  fclose( g_pMasFile );   
  214.  g_pMasFile = NULL;   
  215.    
  216.  return 0;   
  217. }  
  218. //这是打包主函数  
  219.  
  220. int main( void )   
  221. {   
  222.  int ret;   
  223.    
  224.  ret = OpenMasFile( "E:\\PhotoPak.bin",0);   
  225.  if ( ret == -1 )   
  226.      goto __exit;      
  227.  WriteFileToPak( "E:\\珍贵.jpg" );   
  228.  WriteFileToPak( "E:\\123.docx" );   
  229.  WriteFileToPak( "E:\\456.txt" );   
  230.  
  231.  __exit:   
  232.  CloseMasFile();   
  233.  return 0;   
  234. }    
  235. //查看打包中的文件,并且可以解包查看  
  236.  
  237. int main( void )   
  238. {   
  239.  byte*       pBuff;   
  240.  FILE*       pOutFile;   
  241.  FilesMsg    getFileMsg;   
  242.  int         ret;   
  243.    
  244.  ret = OpenMasFile("E:\\PhotoPak.bin", 1);   
  245.  if (ret == -1)   
  246.     goto __exit;   
  247.     
  248.  ret = GetFileMessage("E:\\123.docx", &getFileMsg);   
  249.  if(ret == -1)   
  250.     goto __exit;   
  251.    
  252.  pBuff = (byte*)malloc(getFileMsg.uFileSize);   
  253.  ret = ReadFileFromPak(getFileMsg, pBuff);   
  254.  if(ret == -1)   
  255.      goto __exit_free;   
  256.    
  257.  pOutFile = fopen("E:\\123_out.docx""wb");  // 注意使用的是二进制模式   
  258.  if(ret == -1)   
  259.      goto __exit_free;   
  260.     
  261.  fwrite( pBuff, getFileMsg.uFileSize, 1, pOutFile );   
  262.     fclose( pOutFile );   
  263.         
  264.  __exit_free:   
  265.  free( pBuff );   
  266.    
  267.  __exit:   
  268.     CloseMasFile();   
  269.     return 0;   
  270. }  
  271.