- //测试通过 科嵌电子
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- typedef unsigned int uint;
- typedef unsigned char byte;
- // 包文件中最大可容纳的文件个数
- #define MAX_FILE_COUNT 10
- // 全局包文件指针
- FILE* g_pMasFile = NULL;
- // 资源包文件头结构
- typedef struct SMaseFileHeader
- {
- uint uFileFlag; // 包文件头标记: 'MASE'
- uint uFileCount; // 包内文件个数
- uint uFileListOfs; // 文件列表偏移
- uint uMaxFileCount; // 最大子文件个数
- uint uFileSize; // 包文件的大小
- }MaseHeader;
- // 包内文件信息结构
- typedef struct SFilesMessage
- {
- uint uFileOfs; // 本文件在包内的偏移
- uint uFileSize; // 本文件的大小
- char szFileName[260]; // 本文件的路径
- }FilesMsg;
- // 打开包文件
- int OpenMasFile(const char* path, const byte onlyOpen)
- {
- uint uWriteCount; // 写入文件信息次数
- byte bIsNew = 0; // 是否新建的
- MaseHeader header; // 文件头结构定义
- FilesMsg msg; // 文件信息结构定义
- g_pMasFile = fopen(path, "rb"); // 用来判断是否存在
- if (g_pMasFile == NULL)
- {
- if (onlyOpen == 1) // 只打开不新建
- return -1;
- bIsNew = 1;
- g_pMasFile = fopen(path, "wb");
- if (g_pMasFile == NULL)
- return -1;
- }
- //先关闭,然后在用"rb+"方式打开 二进制读写打开文件
- fclose( g_pMasFile );
- g_pMasFile = fopen(path, "rb+");
- if (g_pMasFile == NULL)
- return -1;
- if(bIsNew == 1)// 新建的文件
- {
- header.uFileFlag = 'ESAM';
- header.uFileCount = 0;
- header.uFileListOfs = sizeof(MaseHeader); //紧跟着就是文件列表
- header.uMaxFileCount = MAX_FILE_COUNT;
- header.uFileSize = sizeof(MaseHeader)
- + (MAX_FILE_COUNT * sizeof(FilesMsg));
- //写入头信息
- fwrite(&header, sizeof(MaseHeader), 1, g_pMasFile);
- memset(&msg, 0, sizeof(FilesMsg));
- uWriteCount = MAX_FILE_COUNT;
- //写入文件列表用0占位
- while(uWriteCount--)
- fwrite(&msg, sizeof(FilesMsg), 1, g_pMasFile);
- }
- else//文件存在
- {
- //则读取头文件信息
- fread(&header, sizeof(MaseHeader), 1, g_pMasFile);
- }
- //检查文件头标记
- if (header.uFileFlag != 'ESAM')
- {
- fclose(g_pMasFile);
- printf("文件头标记不对,错误!\n");
- return -1;
- }
- //检查数据是否完整
- if (header.uMaxFileCount != MAX_FILE_COUNT)
- {
- fclose(g_pMasFile);
- printf("数据不完整,错误!\n");
- return -1;
- }
- return 0;
- }
- //写文件到包里
- int WriteFileToPak(const char* path)
- {
- FilesMsg fileMsg; //此文件的文件信息结构
- MaseHeader header; //包文件头结构定义
- uint uFileSize;
- uint uFileListEndOfs;
- byte* pBuff;
- FILE* pFile = NULL;
- if (g_pMasFile == NULL)
- return -1;
- memset(&fileMsg, 0, sizeof(FilesMsg));
- fseek(g_pMasFile, 0, SEEK_SET); //定位到文件头,读取头文件信息
- //则读取头文件信息
- fread(&header,sizeof(MaseHeader), 1, g_pMasFile);
- uFileListEndOfs = header.uFileCount * sizeof(FilesMsg) + header.uFileListOfs;
- pFile = fopen(path, "rb");
- if(pFile == NULL)
- return -1;
- fseek(pFile, 0, SEEK_END);
- uFileSize = ftell(pFile);
- fseek(pFile, 0, SEEK_SET);
- //文件名长度不能超过260
- strcpy(fileMsg.szFileName,path);
- fileMsg.uFileOfs = header.uFileSize;
- fileMsg.uFileSize = uFileSize;
- // 写入文件信息
- // 将文件指针定位到uFileListEndOfs处,以便写入新的文件信息结构
- fseek(g_pMasFile, uFileListEndOfs, SEEK_SET);
- fwrite(&fileMsg,sizeof(FilesMsg),1,g_pMasFile);
- // 申请空间
- pBuff = (byte*)malloc(uFileSize);
- fread(pBuff,uFileSize,1,pFile);
- // 写数据到包文件里
- fseek(g_pMasFile,header.uFileSize,SEEK_SET);
- fwrite(pBuff, uFileSize, 1, g_pMasFile);
- // 释放内存
- free(pBuff);
- //重新填充header
- header.uFileCount += 1;
- header.uFileSize += uFileSize;
- fseek( g_pMasFile,0,SEEK_SET);
- // 重新写入包文件头
- fwrite(&header,sizeof(MaseHeader),1,g_pMasFile);
- return 0;
- }
- //从包文件里读数据
- int ReadFileFromPak(const FilesMsg msg, byte* _dst)
- {
- if ( g_pMasFile == NULL )
- return -1;
- fseek(g_pMasFile, msg.uFileOfs,SEEK_SET);
- fread(_dst, msg.uFileSize, 1, g_pMasFile);
- return 0;
- }
- //获取包中某个文件的信息
- int GetFileMessage( const char* path, FilesMsg* msg)
- {
- FilesMsg fileMsg; // 此文件的文件信息结构
- MaseHeader header; // 包头结构
- uint uFileCount; // 文件个数
- if ( g_pMasFile == NULL || msg == NULL )
- return -1;
- // 则读取头文件信息
- fseek(g_pMasFile, 0, SEEK_SET);
- fread(&header, sizeof(MaseHeader), 1, g_pMasFile);
- uFileCount = header.uFileCount;
- while (uFileCount--)
- {
- fread(&fileMsg, sizeof(FilesMsg), 1,g_pMasFile);
- // 判断是否是要获取的文件
- if (stricmp(fileMsg.szFileName, path) == 0 )
- {
- *msg = fileMsg;
- return 0;
- }
- }
- return -1;
- }
- // 关闭包文件
- int CloseMasFile( void )
- {
- if ( g_pMasFile == NULL )
- return -1;
- fclose( g_pMasFile );
- g_pMasFile = NULL;
- return 0;
- }
- //这是打包主函数
- int main( void )
- {
- int ret;
- ret = OpenMasFile( "E:\\PhotoPak.bin",0);
- if ( ret == -1 )
- goto __exit;
- WriteFileToPak( "E:\\珍贵.jpg" );
- WriteFileToPak( "E:\\123.docx" );
- WriteFileToPak( "E:\\456.txt" );
- __exit:
- CloseMasFile();
- return 0;
- }
- //查看打包中的文件,并且可以解包查看
- int main( void )
- {
- byte* pBuff;
- FILE* pOutFile;
- FilesMsg getFileMsg;
- int ret;
- ret = OpenMasFile("E:\\PhotoPak.bin", 1);
- if (ret == -1)
- goto __exit;
- ret = GetFileMessage("E:\\123.docx", &getFileMsg);
- if(ret == -1)
- goto __exit;
- pBuff = (byte*)malloc(getFileMsg.uFileSize);
- ret = ReadFileFromPak(getFileMsg, pBuff);
- if(ret == -1)
- goto __exit_free;
- pOutFile = fopen("E:\\123_out.docx", "wb"); // 注意使用的是二进制模式
- if(ret == -1)
- goto __exit_free;
- fwrite( pBuff, getFileMsg.uFileSize, 1, pOutFile );
- fclose( pOutFile );
- __exit_free:
- free( pBuff );
- __exit:
- CloseMasFile();
- return 0;
- }