#include "PackageFileSystem.h" #include "SimpleEncoderBuffer.h" CPackageFileSystem::CPackageFileSystem(bool bModified) :m_bModified(bModified) { m_rootDir.szDirName = ""; MESSAGE_PRINT("New CPackageFileSystem created!"); } //////////////////////////////////////////////////////////////////////////////// //函数名:CPackageFileSystem 拷贝构造函数 //功能:拷贝构造一个文件系统信息 //入口参数: CPackageFileSystem* kSrcSystem 源文件信息系统 //出口参数: 无 //说明: //////////////////////////////////////////////////////////////////////////////// CPackageFileSystem::CPackageFileSystem(CPackageFileSystem* kSrcSystem) { CloneFrom( kSrcSystem ); } void CPackageFileSystem::CloneFrom( CPackageFileSystem* kSrcSystem ) { if ( NULL == kSrcSystem) { return; } m_rootDir = kSrcSystem->m_rootDir; m_vIdleSpace = kSrcSystem->m_vIdleSpace; m_sSystemInfo = kSrcSystem->m_sSystemInfo; m_bModified = false; MESSAGE_PRINT("New CPackageFileSystem created!"); } CPackageFileSystem::~CPackageFileSystem() { m_vIdleSpace.clear(); MESSAGE_PRINT("CPackageFileSystem destroyed!"); } //////////////////////////////////////////////////////////////////////////////// //函数名:AddFileInfo //功能:添加指定文件描述到包文件描述系统 //入口参数: string szPathName 文件全路径(相对路径+文件名) // const SPackageFileInfo& fileInfo 源文件描述信息 //出口参数: bool 成功返回true, 失败返回 false //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::AddFileInfo( string strPathName, const SPackageFileInfo& fileInfo ) { if ( strPathName.size() > MAX_PATH ) { ERROR_PRINT("文件名大于最大限制:PACKAGEFILESYSTEM.CPP-AddFileInfo",NULL); return false; } if (strPathName.empty()) { ERROR_PRINT("文件名不能为空:PACKAGEFILESYSTEM.CPP-AddFileInfo",NULL); return false; } StringLower(strPathName); string strFileName = fileInfo.szFilename; // 首先查找文件描述是否已存在,如果已存在则先删除 if ( GetPackFileInfo( strPathName ) != NULL ) { if( DeleteFileInfo( strPathName ) == false) { ERROR_PRINT("删除已有文件出错:PACKAGEFILESYSTEM.CPP-AddFileInfo",strPathName.c_str()); return false; } } // 找到对应目录 // 如果指定目录不存在,则生成目录 SPackageDirInfo* pDirInfo = _CreateDirInfo( strPathName ); if ( NULL == pDirInfo ) { ERROR_PRINT("获取目录信息失败:PACKAGEFILESYSTEM.CPP-AddFileInfo",strPathName.c_str()); return false; } // 插入文件描述,以文件名为键,以防止同一目录下存在同名文件 pDirInfo->vPackageFileInfos[ strFileName ] = fileInfo; MESSAGE_PRINT("文件信息描述添加成功"); return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:DeleteFileInfo //功能:删除指定文件描述 //入口参数: string szPathName 文件全路径 //出口参数: bool //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::DeleteFileInfo( string strPathName ) { if (m_bModified == false) { ERROR_PRINT("只读模式不可修改文件信息描述:PACKAGEFILESYSTEM.CPP-DeleteFileInfo",NULL); return false; } if (strPathName.empty()) { ERROR_PRINT("文件名不能为空:PACKAGEFILESYSTEM.CPP-DeleteFileInfo",NULL); return false; } StringLower( strPathName ); SPackageDirInfo* pDirInfo = _GetPackDirInfo( strPathName ); if ( NULL == pDirInfo ) { ERROR_PRINT("所删除文件描述的目录不存在:PACKAGEFILESYSTEM.CPP-DeleteFileInfo",strPathName.c_str()); return false; } string strFileName = strPathName.substr( strPathName.find_last_of("\\") + 1 ); map::iterator fileIt = pDirInfo->vPackageFileInfos.find( strFileName ); if ( fileIt != pDirInfo->vPackageFileInfos.end() ) { SPackageIdleSpaceInfo sIdleInfo; sIdleInfo.nPos = fileIt->second.nPos; sIdleInfo.nRegionSize = fileIt->second.nFileSize; // 删除一个文件描述 pDirInfo->vPackageFileInfos.erase( fileIt ); // 添加一个碎片空间 m_vIdleSpace.push_back( sIdleInfo ); sort(m_vIdleSpace.begin(),m_vIdleSpace.end(),CompareIdleSpace); /*if(!_AddIdleSpace(sIdleInfo)) { ERROR_PRINT("添加碎片空间失败:PACKAGEFILESYSTEM.CPP-DeleteFileInfo",NULL); return false; }*/ } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:GetIdleSpace //功能:获得大于等于指定大小的碎片空间 //入口参数: UINT nSize 空间大小 // SPackageIdleSpaceInfo& sIdleInfo 碎片空间信息的引用 // bool bUse 是否使用改碎片空间,ture 则在返回碎片空间的同时删除该空间,反之仅返回该空间 //出口参数: bool 找到返回 ture,反之返回 false //说明:找到则由sIfleInfo返回找到的碎片空间信息 //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::GetIdleSpace( UINT nSize,SPackageIdleSpaceInfo& sIdleInfo, bool bUse ) { if (m_bModified == false && bUse == true) { ERROR_PRINT("只读模式,不可修改描述信息:PACKAGEFILESYSTEM.CPP-GetIdleSpace",NULL); return false; } if ( m_vIdleSpace.empty()) { MESSAGE_PRINT("没有碎片空间:PACKAGEFILESYSTEM.CPP-GetIdleSpace"); return false; } // 查询模式 if (bUse == false) { for (vector::size_type uiIndex = 0; uiIndex < m_vIdleSpace.size(); uiIndex++) { if (m_vIdleSpace[uiIndex].nRegionSize >= nSize) { sIdleInfo.nPos = m_vIdleSpace[uiIndex].nPos; return true; } } } // 使用模式 else if (bUse == true && m_bModified == true) { vector::iterator it = m_vIdleSpace.begin(); for (; it != m_vIdleSpace.end(); it++) { if (it->nRegionSize >= nSize) { // 找到比文件大的碎片空间,则分配给适当的空间 // 再将碎片空间差分为新的可用碎片空间,添加如可用空间中 UINT uTemp = it->nRegionSize - nSize; SPackageIdleSpaceInfo sNewIdleSpace; if (uTemp > 0) { sNewIdleSpace.nPos = it->nPos + nSize; sNewIdleSpace.nRegionSize = uTemp; } //更新原有的碎片空间信息 it->nRegionSize = nSize; sIdleInfo.nPos = it->nPos; sIdleInfo.nRegionSize = nSize; m_vIdleSpace.erase(it); if (uTemp > 0) { m_vIdleSpace.push_back( sNewIdleSpace ); } sort(m_vIdleSpace.begin(),m_vIdleSpace.end(),CompareIdleSpace); /*if (_DeleteIdleSpace(m_vIdleSpace[uiIndex]) == false) { ERROR_PRINT("删除碎片空间失败:PACKAGEFILESYSTEM.CPP-GetIdleSpace",NULL); return false; }*/ return true; } } //for (vector::size_type uiIndex = 0; uiIndex < m_vIdleSpace.size(); uiIndex++) //{ // if (m_vIdleSpace[uiIndex].nRegionSize >= nSize) // { // // 找到比文件大的碎片空间,则分配给适当的空间 // // 再将碎片空间差分为新的可用碎片空间,添加如可用空间中 // UINT uTemp = m_vIdleSpace[uiIndex].nRegionSize - nSize; // if (uTemp > 0) // { // SPackageIdleSpaceInfo sNewIdleSpace; // sNewIdleSpace.nPos = m_vIdleSpace[uiIndex].nPos + nSize; // sNewIdleSpace.nRegionSize = uTemp; // m_vIdleSpace.push_back( sIdleInfo ); // sort(m_vIdleSpace.begin(),m_vIdleSpace.end,CompareIdleSpace); // /*if (_AddIdleSpace(sNewIdleSpace) == false) // { // ERROR_PRINT("添加新碎片空间失败:PACKAGEFILESYSTEM.CPP-GetIdleSpace",NULL); // return false; // } */ // } // // 更新原有的碎片空间信息 // m_vIdleSpace[uiIndex].nRegionSize = nSize; // sIdleInfo.nPos = m_vIdleSpace[uiIndex].nPos; // m_vIdleSpace // /*if (_DeleteIdleSpace(m_vIdleSpace[uiIndex]) == false) // { // ERROR_PRINT("删除碎片空间失败:PACKAGEFILESYSTEM.CPP-GetIdleSpace",NULL); // return false; // }*/ // return true; // } //} } // 没有找到合适的空间 MESSAGE_PRINT("没有找到可用碎片空间 "); return false; } SPackageDirInfo* CPackageFileSystem::GetPackDirInfo( string szPathName ) { if ( szPathName.empty() ) { ERROR_PRINT("文件名不能为空:PACKAGEFILESYSTEM.CPP-GetPackFileInfo",NULL); return NULL; } if ( szPathName[szPathName.length() - 1] != '\\' ) szPathName += "\\"; // 转换所有路径为小写字母 StringLower(szPathName); // 查找文件夹 return _GetPackDirInfo( szPathName ); } //////////////////////////////////////////////////////////////////////////////// //函数名:GetPackFileInfo //功能:获得指定文件的文件描述信息 //入口参数: string szPathName 文件全路径(相对路径+文件名) //出口参数: SPackageFileInfo* 文件信息描述指针,如果未找到则返回NULL //说明: //////////////////////////////////////////////////////////////////////////////// SPackageFileInfo* CPackageFileSystem::GetPackFileInfo( string szPathName ) { if (szPathName.empty()) { ERROR_PRINT("文件名不能为空:PACKAGEFILESYSTEM.CPP-GetPackFileInfo",NULL); return NULL; } // 转换所有路径为小写字母 StringLower(szPathName); // 查找文件夹 SPackageDirInfo* pDirInfo = _GetPackDirInfo( szPathName ); if ( NULL == pDirInfo ) { //ERROR_PRINT("文件不存在:PACKAGEFILESYSTEM.CPP-GetPackFileInfo"); return NULL; } // 定位文件名 string strRelPath = szPathName.substr( szPathName.find_last_of("\\") + 1 ); if ( pDirInfo ) { map::iterator fileInfoIt = pDirInfo->vPackageFileInfos.find( strRelPath ); if ( fileInfoIt == pDirInfo->vPackageFileInfos.end() ) { //ERROR_PRINT("文件不存在:PACKAGEFILESYSTEM.CPP-GetPackFileInfo"); return NULL; } else { return &fileInfoIt->second; } } return NULL; } //////////////////////////////////////////////////////////////////////////////// //函数名:GetPackDirInfo //功能:获得指定路径的目录描述信息 //入口参数: string szPathName 相对路径 //出口参数: SPackageDirInfo* 目录信息指针,如果未找到则返回NULL //说明: //////////////////////////////////////////////////////////////////////////////// SPackageDirInfo* CPackageFileSystem::_GetPackDirInfo( string szPathName ) { if (szPathName.empty()) { ERROR_PRINT("文件名不能为空:PACKAGEFILESYSTEM.CPP-GetPackDirInfo",NULL); return NULL; } StringLower(szPathName); // 分解路径为文件夹名和文件名 vector vFilePath; _GetPathSegment( szPathName.c_str(), vFilePath); // 路径中文件夹的个数 最后一组字符串是文件名及其类型 vector::size_type uiNum = vFilePath.size() - 1; SPackageDirInfo* pDirInfo = &m_rootDir; for ( vector::size_type uiIndex = 0; uiIndex < uiNum; uiIndex++ ) { map::iterator dirIt = pDirInfo->vPackageDirInfos.find(vFilePath[uiIndex]); if ( dirIt == pDirInfo->vPackageDirInfos.end() ) { //ERROR_PRINT("文件不存在:PACKAGEFILESYSTEM.CPP-GetPackDirInfo"); return NULL; } else { pDirInfo = &dirIt->second; /*cerr << "文件夹" << vFilePath[uiIndex] << "找到" << endl;*/ } } return pDirInfo; } //////////////////////////////////////////////////////////////////////////////// //函数名:GetRelPath //功能:获得相对路径 //入口参数: string strAbsPath 源路径 //出口参数: string 相对路径 //说明: //////////////////////////////////////////////////////////////////////////////// string CPackageFileSystem::GetRelPath( string strAbsPath ) { if (strAbsPath.empty()) { ERROR_PRINT("文件名不能为空:PACKAGEFILESYSTEM.CPP-GetRelPath",NULL); return strAbsPath; } if (IsRoot(strAbsPath) == true) { return ""; } if (m_rootDir.szDirName.empty()) { return ""; } StringLower( strAbsPath ); return _GetRelativePath(m_rootDir.szDirName.c_str(), strAbsPath.c_str());; } //////////////////////////////////////////////////////////////////////////////// //函数名:_CreateDirInfo //功能:创建目录信息 //入口参数: string strDirName 源目录路径 //出口参数: SPackageDirInfo* 目录信息指针 //说明: //////////////////////////////////////////////////////////////////////////////// SPackageDirInfo* CPackageFileSystem::_CreateDirInfo( string strDirName ) { if (strDirName.empty()) { ERROR_PRINT("文件名不能为空:PACKAGEFILESYSTEM.CPP-_CreateDirInfo",NULL); return NULL; } // 分解路径为文件夹名和文件名 vector vFilePath; _GetPathSegment( strDirName.c_str(), vFilePath ); // 路径中文件夹的个数 最后一组字符串是文件名及其类型 vector::size_type uiNum = vFilePath.size() - 1; SPackageDirInfo* pDirInfo = &m_rootDir; for ( vector::size_type uiIndex = 0; uiIndex < uiNum; uiIndex++ ) { map::iterator dirIt = pDirInfo->vPackageDirInfos.find(vFilePath[uiIndex]); if ( dirIt == pDirInfo->vPackageDirInfos.end() ) { /*cerr << "文件夹" << vFilePath[uiIndex] << "不存在,将创建对应文件夹" << endl;*/ // 插入文件夹描述,以文件夹名为键 SPackageDirInfo sDirInfo; sDirInfo.szDirName = vFilePath[uiIndex]; pDirInfo->vPackageDirInfos[ vFilePath[uiIndex] ] = sDirInfo; // 递归到下一个文件夹 pDirInfo = &pDirInfo->vPackageDirInfos[ vFilePath[uiIndex] ]; /*cerr << "文件夹创建成功" << endl;*/ } else { // 递归到下一个文件夹 pDirInfo = &dirIt->second; /*cerr << "文件夹" << vFilePath[uiIndex] << "找到" << endl;*/ } } return pDirInfo; } //////////////////////////////////////////////////////////////////////////////// //函数名:LoadPackFileSystem //功能:从包文件载入包系统信息 //入口参数: FILE* pPackFile 包文件 // UINT nSystemInfoPos 文件系统信息存储位置 // bool bModified 当前系统模式 //出口参数: bool 成功返回true, 失败返回 false //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::LoadPackFileSystem( FILE* pPackFile, UINT nSystemInfoPos, bool bModified ) { if ( NULL == pPackFile ) { ERROR_PRINT("包文件打开失败:PACKAGEFILESYSTEM.CPP-LoadPackFileSystem",NULL); return false; } m_bModified = bModified; //初始化根目录,同时改写nFilePos到文件描述信息存储位置 if ( _LoadSystemInfo(pPackFile,nSystemInfoPos) == false ) { ERROR_PRINT("读取根目录信息失败:PACKAGEFILESYSTEM.CPP-LoadPackFileSystem",NULL); return false; } //初始化文件描述 if ( _LoadFileInfos(pPackFile,m_sSystemInfo.nFileInfoPos) == false ) { ERROR_PRINT("读取文件信息描述失败:PACKAGEFILESYSTEM.CPP-LoadPackFileSystem",NULL ); return false; } //初始化碎片空间信息 if ( _LoadIdleInfo( pPackFile, m_sSystemInfo.nIdleInfoPos ) == false ) { ERROR_PRINT("读取碎片空间信息描述失败:PACKAGEFILESYSTEM.CPP-LoadPackFileSystem",NULL); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:SavePackFileSystemInfo //功能:向包文件写入包系统信息 //入口参数: FILE* pPackFile 包文件 // UINT nPos 文件系统信息存储位置 //出口参数: UINT 文件系统信息在包文件中的最后写入位置 //说明: //////////////////////////////////////////////////////////////////////////////// UINT CPackageFileSystem::SavePackFileSystemInfo( FILE* pPackFile,UINT nPos,FILETIME nContentVersion ) { if ( NULL == pPackFile ) { ERROR_PRINT("包文件打开失败:PACKAGEFILESYSTEM.CPP-SavePackFileSystemInfo",NULL); return 0; } if (m_bModified == false) { ERROR_PRINT("只读模式不可改写文件信息系统:PACKAGEFILESYSTEM.CPP-SavePackFileSystemInfo",NULL); return 0; } // nPos处开始写文件信息 // 获得文件信息存储的末位,用于写碎片空间 UINT nIdleInfoPos = _SaveFileInfoToPackage( pPackFile,nPos ); if ( nIdleInfoPos == 0 ) { ERROR_PRINT("文件信息描述存储错误:存储位置错误:PACKAGEFILESYSTEM.CPP-SavePackFileSystemInfo",NULL); return 0; } // 获得碎片空间存储的末位,用于写系统信息 UINT nSystemPos = _SaveFileIdleSpaceInfoToPackage( pPackFile,nIdleInfoPos ); if ( nSystemPos == 0 ) { ERROR_PRINT("碎片空间信息描述存储错误:存储位置错误:PACKAGEFILESYSTEM.CPP-SavePackFileSystemInfo",NULL); return 0; } // 获得文件结尾 UINT nLastPos = _SaveSystemInfoToPackage( pPackFile,nSystemPos ); if ( nLastPos == 0 ) { ERROR_PRINT("文件系统描述存储错误:存储位置错误:PACKAGEFILESYSTEM.CPP-SavePackFileSystemInfo",NULL); return 0; } //// 改写包头信息中的内容版本号 [4/14/2009 hemeng] fseek( pPackFile, sizeof(UINT) + sizeof(UINT), SEEK_SET ); // write filetime to package file if (fwrite(&nContentVersion,sizeof(FILETIME),1,pPackFile) != 1) { ERROR_PRINT("写入包内容版本出错:PACKAGEFILESYSTEM.CPP-SavePackFileSystemInfo",NULL); return 0; } // 改写包头信息中的系统信息偏移量 if ( fwrite( &nSystemPos, sizeof(UINT), 1, pPackFile ) != 1 ) { ERROR_PRINT("写入包文件信息系统出错:PACKAGEFILESYSTEM.CPP-SavePackFileSystemInfo",NULL); return 0; } //返回文件最终位置 return nLastPos; } //////////////////////////////////////////////////////////////////////////////// //函数名:FindAllFileInfos //功能:由当前文件系统和比对文件系统对比,查找是否相同 //入口参数: vector& vFilesName 当前文件系统所有文件 //出口参数: bool 成功返回true, 失败返回 false //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::FindAllFilesName(vector& vFilesName) { vector vFileInfos; _InsertAllFileInfoToVector( vFileInfos ); while (vFileInfos.size() > 0) { SPackageFileInfo curFileInfo = vFileInfos[0]; vFilesName.push_back(curFileInfo.szFullPathName); vFileInfos.erase(vFileInfos.begin()); } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_SaveSystemInfoToPackage //功能:写入包系统信息到包文件 //入口参数: FILE* pPackFile 包文件流指针 // UINT nPos 写入位置 //出口参数: 最终写入位置 //说明: //////////////////////////////////////////////////////////////////////////////// UINT CPackageFileSystem::_SaveSystemInfoToPackage( FILE* pPackFile,UINT nPos ) { m_sSystemInfo.strRootDir = m_rootDir.szDirName; if ( m_sSystemInfo.strRootDir.empty() ) { ERROR_PRINT("存储包信息失败:包统计信息根目录未初始化:PACKAGEFILESYSTEM.CPP-_SaveSystemInfoToPackage",NULL); return 0; } if ( NULL == pPackFile ) { ERROR_PRINT("文件未打开:PACKAGEFILESYSTEM.CPP-_SaveSystemInfoToPackage",NULL); return 0; } if (m_bModified == false) { ERROR_PRINT("只读模式不可改写文件信息系统:PACKAGEFILESYSTEM.CPP-_SaveSystemInfoToPackage",NULL); return 0; } return _WriteSystemInfoToPackage( pPackFile, m_sSystemInfo,nPos ); } //////////////////////////////////////////////////////////////////////////////// //函数名:_SaveFileInfoToPackage //功能:写入文件描述信息到包文件 //入口参数: FILE* pPackFile 包文件流指针 // UINT nPos 写入位置 //出口参数: 最终写入位置 //说明: //////////////////////////////////////////////////////////////////////////////// UINT CPackageFileSystem::_SaveFileInfoToPackage( FILE* pPackFile,UINT nPos ) { if (m_bModified == false) { ERROR_PRINT("只读模式不可修改信息系统:PACKAGEFILESYSTEM.CPP-_SaveFileInfoToPackage",NULL); return 0; } vector vAllPackFileInfos; _InsertAllFileInfoToVector(vAllPackFileInfos); // 记录所有文件的个数 m_sSystemInfo.nFileInfoNum = (UINT)vAllPackFileInfos.size(); m_sSystemInfo.nFileInfoPos = nPos; if ( NULL == pPackFile) { ERROR_PRINT( "文件未打开:PACKAGEFILESYSTEM.CPP-_SaveFileInfoToPackage",NULL); return 0; } UINT nCurrPos = nPos; while (vAllPackFileInfos.size() > 0) { SPackageFileInfo curFileInfo = vAllPackFileInfos[0]; vAllPackFileInfos.erase(vAllPackFileInfos.begin()); nPos = _WriteFileInfoToPackage(pPackFile, curFileInfo, nCurrPos); if (nPos == 0) { return 0; } nCurrPos = nPos; } return ftell( pPackFile ); } //////////////////////////////////////////////////////////////////////////////// //函数名:_SaveFileIdleSpaceInfoToPackage //功能:写入碎片空间信息到包文件 //入口参数: FILE* pPackFile 包文件流指针 // UINT nPos 写入位置 //出口参数: 最终写入位置 //说明: //////////////////////////////////////////////////////////////////////////////// UINT CPackageFileSystem::_SaveFileIdleSpaceInfoToPackage( FILE* pPackFile,UINT nPos ) { if (m_bModified == false) { ERROR_PRINT("只读模式不可改写信息系统:PACKAGEFILESYSTEM.CPP-_SaveFileIdleSpaceInfoToPackage",NULL); return 0; } if ( NULL == pPackFile ) { ERROR_PRINT( "文件未打开:PACKAGEFILESYSTEM.CPP-_SaveFileIdleSpaceInfoToPackage",NULL); return 0; } m_sSystemInfo.nIdleInfoNum = (UINT)m_vIdleSpace.size(); m_sSystemInfo.nIdleInfoPos = nPos; // 定位到指定位置 fseek( pPackFile, nPos,SEEK_SET ); vector::iterator it = m_vIdleSpace.begin(); for (; it != m_vIdleSpace.end(); it ++) { if (_Encoderfwrite( &(*it), sizeof(SPackageIdleSpaceInfo), 1, pPackFile ) != 1) { ERROR_PRINT("写入碎片空间数据错误:PACKAGEFILESYSTEM.CPP-_SaveFileIdleSpaceInfoToPackage",NULL); return 0; } } //for ( vector::size_type uiIndex = 0; uiIndex < m_vIdleSpace.size(); uiIndex++ ) //{ // SPackageIdleSpaceInfo sIdleInfo = m_vIdleSpace[uiIndex]; // // 检测写入状态 // if ( /*fwrite*/_Encoderfwrite( &sIdleInfo.nPos, sizeof(SPackageIdleSpaceInfo), 1, pPackFile ) != 1 ) // { // ERROR_PRINT("写入碎片空间数据错误:PACKAGEFILESYSTEM.CPP-_SaveFileIdleSpaceInfoToPackage",NULL); // return 0; // } // //} return ftell( pPackFile ); } //////////////////////////////////////////////////////////////////////////////// //函数名:_InsertAllFileInfoToVector //功能: 将包系统中的所有文件信息插入一个容器中 //入口参数: vector& vPackageFileInfos 目标容器 //出口参数: 无 //说明: //////////////////////////////////////////////////////////////////////////////// void CPackageFileSystem::_InsertAllFileInfoToVector( vector& vPackageFileInfos ) { vPackageFileInfos.clear(); SPackageDirInfo currDirInfo = m_rootDir; _InsertDirInfoToVector( vPackageFileInfos, m_rootDir ); } //////////////////////////////////////////////////////////////////////////////// //函数名:_InsertDirInfoToVector //功能:将指定目录信息中的所有文件信息插入目标容器 //入口参数: vector& vPackageFileInfos 目标容器 // SPackageDirInfo& sDirInfo 源目录信息 //出口参数: 无 //说明: //////////////////////////////////////////////////////////////////////////////// void CPackageFileSystem::_InsertDirInfoToVector( vector& vPackageFileInfos, SPackageDirInfo& sDirInfo ) { // 首先将当前文件夹下的文件压入堆栈 for ( map::iterator fileIt = sDirInfo.vPackageFileInfos.begin(); fileIt != sDirInfo.vPackageFileInfos.end(); fileIt++ ) { vPackageFileInfos.push_back( fileIt->second ); } // 查找子文件夹下的文件 for ( map::iterator dirIt = sDirInfo.vPackageDirInfos.begin(); dirIt != sDirInfo.vPackageDirInfos.end(); dirIt++) { SPackageDirInfo subDirInfo = dirIt->second; _InsertDirInfoToVector( vPackageFileInfos,subDirInfo ); } } //////////////////////////////////////////////////////////////////////////////// //函数名:_LoadSystemInfo //功能:载入包系统信息 //入口参数: FILE* pPackFile 包文件流指针 // UINT nPos 系统信息在包中的存储位置 //出口参数: //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::_LoadSystemInfo( FILE* pPackFile,UINT nPos ) { if ( NULL == pPackFile ) { ERROR_PRINT( "文件未打开:PACKAGEFILESYSTEM.CPP-_LoadSystemInfo",NULL); return false; } UINT nCurrPos = nPos; if ( _ReadSystemInfoFromPackage( pPackFile, m_sSystemInfo,nCurrPos ) == false) { ERROR_PRINT("系统信息读入失败:PACKAGEFILESYSTEM.CPP-_LoadSystemInfo",NULL); return false; } m_rootDir.szDirName = m_sSystemInfo.strRootDir; /*cerr << "根目录为:" << m_rootDir.szDirName << endl;*/ return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_LoadFileInfos //功能:载入文件信息描述 //入口参数: FILE* pPackFile 包文件流指针 // UINT nPos 信息在包中的存储位置 //出口参数: bool 成功返回ture,失败返回false //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::_LoadFileInfos( FILE* pPackFile,UINT nFileInfoPos ) { if ( NULL == pPackFile ) { ERROR_PRINT("包文件未打开:PACKAGEFILESYSTEM.CPP-_LoadFileInfos",NULL); return false; } UINT nPos = nFileInfoPos; for ( UINT nCurrPos = 0; nCurrPos < m_sSystemInfo.nFileInfoNum ; nCurrPos++ ) { SPackageFileInfo sFileInfo; if ( _ReadFileInfoFromPackage( pPackFile, sFileInfo, nPos ) == false ) { ERROR_PRINT("读取文件描述失败:PACKAGEFILESYSTEM.CPP-_LoadFileInfos",NULL); return false; } if ( AddFileInfo( sFileInfo.szFullPathName, sFileInfo ) == false ) { ERROR_PRINT("读取文件描述失败:插入读取信息失败:PACKAGEFILESYSTEM.CPP-_LoadFileInfos",NULL); return false; } } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_LoadIdleInfo //功能:载入碎片空间 //入口参数: FILE* pPackFile 包文件流指针 // UINT nPos 信息在包中的存储位置 //出口参数: bool 成功返回ture,失败返回false //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::_LoadIdleInfo( FILE* pPackFile,UINT nPos ) { if ( NULL == pPackFile ) { ERROR_PRINT("包文件未打开:PACKAGEFILESYSTEM.CPP-_LoadIdleInfo",NULL); return false; } // 偏移读指针到指定位置 fseek( pPackFile, nPos, SEEK_SET ); for ( UINT nCount = 0; nCount < m_sSystemInfo.nIdleInfoNum ; nCount++ ) { SPackageIdleSpaceInfo sIdleInfo; /*fread*/_Decoderfread( &sIdleInfo.nPos, sizeof(SPackageIdleSpaceInfo), 1, pPackFile ); if ( feof(pPackFile) ) { ERROR_PRINT("读取文件失败:PACKAGEFILESYSTEM.CPP-_LoadIdleInfo",NULL); return false; } m_vIdleSpace.push_back( sIdleInfo ); } if ( (UINT)m_vIdleSpace.size() != m_sSystemInfo.nIdleInfoNum ) { ERROR_PRINT("碎片空间个数与文件记录数目不符:PACKAGEFILESYSTEM.CPP-_LoadIdleInfo",NULL); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:SetPackageRootDir //功能:设置包的根目录 //入口参数: string strRootDir 根目录 //出口参数: 无 //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::SetPackageRootDir(string strRootDir) { if (m_bModified == false) { ERROR_PRINT("只读模式不可修改信息系统:PACKAGEFILESYSTEM.CPP-SetPackageRootDir",NULL); return false; } if ( strRootDir.empty()) { return false; } StringLower( strRootDir ); m_rootDir.szDirName = strRootDir; m_sSystemInfo.strRootDir = strRootDir; return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:Deflate //功能:紧凑模式 //入口参数: FILE* pPackFile 源包文件流指针 //出口参数: //说明:bool 成功返回true, 失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::Deflate( FILE* pPackFile ) { if ( NULL == pPackFile ) { return false; } if (!m_bModified) { return false; } // 没有碎片空间 if ( m_vIdleSpace.empty() ) { return true; } // 所有碎片空间的大小总和 UINT nDeflateSize = 0; vector vFileInfos; _InsertAllFileInfoToVector( vFileInfos ); // 没有文件 if ( vFileInfos.empty() ) { return true; } // 排序 sort( vFileInfos.begin(),vFileInfos.end(), CompareFileInfo ); sort( m_vIdleSpace.begin(),m_vIdleSpace.end(),CompareIdleSpace ); // 判断是否移动 for ( UINT uiIdleIndex = 0; uiIdleIndex < m_vIdleSpace.size() ; uiIdleIndex++ ) { for ( UINT uiIndex = 0; uiIndex < vFileInfos.size(); uiIndex++ ) { if ( vFileInfos[uiIndex].nPos > m_vIdleSpace[uiIdleIndex].nPos ) { if ( !_MoveFileData(pPackFile,vFileInfos[uiIndex], m_vIdleSpace[uiIdleIndex].nRegionSize) ) { ERROR_PRINT("移动文件数据出错:PACKAGEFILESYSTEM.CPP-Deflate",vFileInfos[uiIndex].szFullPathName.c_str()); return false; } else { SPackageFileInfo* pCurrFileInfo = GetPackFileInfo(vFileInfos[uiIndex].szFullPathName); if ( NULL == pCurrFileInfo ) { ERROR_PRINT("紧缩模式:查找移动数据文件信息出错:PACKAGEFILESYSTEM.CPP-Deflate",vFileInfos[uiIndex].szFullPathName.c_str()); return false; } else { vFileInfos[uiIndex].nPos -= m_vIdleSpace[uiIdleIndex].nRegionSize; pCurrFileInfo->nPos = vFileInfos[uiIndex].nPos; } } } } nDeflateSize += m_vIdleSpace[uiIdleIndex].nRegionSize; } m_vIdleSpace.clear(); m_sSystemInfo.nFileInfoPos -= nDeflateSize; m_sSystemInfo.nIdleInfoNum = 0; m_sSystemInfo.nIdleInfoPos -= nDeflateSize; return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:_MoveFileData //功能: 移动包数据,用于紧缩模式 //入口参数: FILE* pPackFile 包文件流 // SPackageFileInfo sFileInfo 当前移动数据的文件描述信息 // UINT nMoveOffset 向上移动的偏移量 //出口参数: bool 成功返回ture,失败返回false //说明: //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::_MoveFileData( FILE* pPackFile,SPackageFileInfo sFileInfo, UINT nMoveOffset ) { if (m_bModified == false) { ERROR_PRINT("只读模式,不可移动数据:PACKAGEFILESYSTEM.CPP-_MoveFileData",NULL); return false; } if ( pPackFile == NULL ) { return false; } UINT nFilePos = sFileInfo.nPos; // 存放 BYTE* pFileBuffer = new BYTE[sFileInfo.nFileSize]; if ( NULL == pFileBuffer ) { ERROR_PRINT("申请内存失败:PACKAGEFILESYSTEM.CPP-_MoveFileData",sFileInfo.szFullPathName.c_str()); return false; } fseek( pPackFile, nFilePos, SEEK_SET ); fread( pFileBuffer, sFileInfo.nFileSize, 1,pPackFile ); if ( ferror( pPackFile ) ) { ERROR_PRINT("读入数据失败:PACKAGEFILESYSTEM.CPP-_MoveFileData",sFileInfo.szFullPathName.c_str()); delete [] pFileBuffer; pFileBuffer = NULL; return false; } // 新位置 nFilePos -= nMoveOffset; fseek( pPackFile, nFilePos, SEEK_SET ); if ( fwrite( pFileBuffer, sFileInfo.nFileSize,1,pPackFile ) != 1 ) { ERROR_PRINT("写入数据失败:PACKAGEFILESYSTEM.CPP-_MoveFileData",sFileInfo.szFullPathName.c_str()); delete [] pFileBuffer; pFileBuffer = NULL; return false; } if ( pFileBuffer ) { delete [] pFileBuffer; pFileBuffer = NULL; } return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:WriteSystemInfoToPackage //功能:将包系统信息写入指定文件 //入口参数: FILE* pFile 目标文件流指针 // SFileSystemInfo& sSystemInfo 源包系统信息 // UINT nPos 写入位置 //出口参数: UINT 写入文件的最后位置 //////////////////////////////////////////////////////////////////////////////// UINT CPackageFileSystem::_WriteSystemInfoToPackage( FILE* pFile, SFileSystemInfo& sSystemInfo, UINT nPos ) { if (m_bModified == false) { ERROR_PRINT("只读模式不可改写信息系统:PACKAGEFILESYSTEM.CPP-_WriteSystemInfoToPackage",NULL); return 0; } if (NULL == pFile) { return 0; } // 偏移读指针到指定位置 fseek( pFile, nPos, SEEK_SET ); UINT nRootDirLen = (UINT)sSystemInfo.strRootDir.size(); if ( /*fwrite*/_Encoderfwrite( &nRootDirLen, sizeof(UINT), 1, pFile ) != 1 ) { ERROR_PRINT("写入文件信息系统数据错误:PACKAGEFILESYSTEM.CPP-_WriteSystemInfoToPackage",NULL); return 0; } if ( fputs( sSystemInfo.strRootDir.c_str(), pFile ) == EOF ) { ERROR_PRINT("写入文件信息系统数据错误:PACKAGEFILESYSTEM.CPP-_WriteSystemInfoToPackage",NULL); return 0; } if ( /*fwrite*/_Encoderfwrite( &sSystemInfo.nFileInfoPos, sizeof(UINT),1, pFile ) != 1 ) { ERROR_PRINT("写入文件信息系统数据错误:PACKAGEFILESYSTEM.CPP-_WriteSystemInfoToPackage",NULL); return 0; } // 写入压缩加密类型 if ( /*fwrite*/_Encoderfwrite( &sSystemInfo.nFileInfoNum, sizeof(UINT),1, pFile ) != 1) { ERROR_PRINT("写入文件信息系统数据错误:PACKAGEFILESYSTEM.CPP-_WriteSystemInfoToPackage",NULL); return 0; } // 写入文件所在位置 if ( /*fwrite*/_Encoderfwrite( &sSystemInfo.nIdleInfoPos, sizeof(UINT),1, pFile ) != 1 ) { ERROR_PRINT("写入文件信息系统数据错误 :PACKAGEFILESYSTEM.CPP-_WriteSystemInfoToPackage",NULL); return 0; } // 写入文件大小 if ( /*fwrite*/_Encoderfwrite( &sSystemInfo.nIdleInfoNum, sizeof(UINT),1, pFile ) != 1 ) { ERROR_PRINT("写入文件信息系统数据错误:PACKAGEFILESYSTEM.CPP-_WriteSystemInfoToPackage",NULL); return 0; } return ftell( pFile ); } //////////////////////////////////////////////////////////////////////////////// //函数名:ReadSystemInfoFromPackage //功能:从指定文件读取包系统信息 //入口参数: FILE* pFile 源文件流指针 // SFileSystemInfo& sSystemInfo 目标包系统信息 // UINT nPos 读入位置 返回读入最后位置 //出口参数: bool 成功返回ture 失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::_ReadSystemInfoFromPackage( FILE* pFile, SFileSystemInfo& sSystemInfo, UINT& nPos ) { if (NULL == pFile) { return false; } //偏移读指针到指定位置 fseek( pFile, nPos, SEEK_SET ); UINT nRootDirLen = 0; //路径字符串长度 /*fread*/_Decoderfread( &nRootDirLen, sizeof(UINT), 1, pFile ); if ( feof(pFile) ) { return false; } //'\0'占一位 char *pChar = new char[nRootDirLen+1]; if ( NULL == pChar ) { ERROR_PRINT("申请内存出错:PACKAGEFILESYSTEM.CPP-_ReadSystemInfoFromPackage",NULL); return NULL; } if ( !fgets( pChar, nRootDirLen+1, pFile ) ) { ERROR_PRINT("从包文件读取文件系统信息数据失败:PACKAGEFILESYSTEM.CPP-_ReadSystemInfoFromPackage",NULL); delete [] pChar; pChar = NULL; return false; } sSystemInfo.strRootDir = string( pChar ); /*fread*/_Decoderfread( &sSystemInfo.nFileInfoPos, sizeof(UINT),1, pFile ); if ( feof(pFile) ) { delete [] pChar; pChar = NULL; return false; } /*fread*/_Decoderfread( &sSystemInfo.nFileInfoNum, sizeof(UINT),1, pFile ); if ( feof(pFile) ) { delete [] pChar; pChar = NULL; return false; } /*fread*/_Decoderfread( &sSystemInfo.nIdleInfoPos, sizeof(UINT),1, pFile ); if ( feof(pFile) ) { delete [] pChar; pChar = NULL; return false; } /*fread*/_Decoderfread( &sSystemInfo.nIdleInfoNum, sizeof(UINT),1, pFile ); if ( feof(pFile) ) { delete [] pChar; pChar = NULL; return false; } delete [] pChar; pChar = NULL; nPos = ftell(pFile); return true; } //////////////////////////////////////////////////////////////////////////////// //函数名:WriteFileInfoToPackage //功能:将文件信息写入指定文件 //入口参数: FILE* pFile 目标文件流指针 // SPackageFileInfo& sFileInfo 源包文件信息 // UINT nPos 写入位置 //出口参数: UINT 写入文件的最后位置 //////////////////////////////////////////////////////////////////////////////// UINT CPackageFileSystem::_WriteFileInfoToPackage( FILE* pFile, SPackageFileInfo& sFileInfo, UINT nPos ) { if (m_bModified == false) { ERROR_PRINT("只读模式不可改写信息系统:PACKAGEFILESYSTEM.CPP-_WriteFileInfoToPackage",NULL); return 0; } if (NULL == pFile) { return 0; } // 偏移读指针到指定位置 fseek( pFile, nPos, SEEK_SET ); // 写入路径字符串长度 UINT nLen = (UINT)sFileInfo.szFullPathName.size(); if ( /*fwrite*/_Encoderfwrite( &nLen, sizeof(UINT), 1, pFile ) != 1) { return 0; } // 写入全路径 string szFullPathName = sFileInfo.szFullPathName; if ( fputs( szFullPathName.c_str(), pFile ) == EOF ) { return 0; } // 写入文件类型 if ( /*fwrite*/_Encoderfwrite( &sFileInfo.eFileType, sizeof(UINT),1, pFile ) != 1) { return 0; } // 写入压缩加密类型 if ( /*fwrite*/_Encoderfwrite( &sFileInfo.eEncryptType, sizeof(UINT), 1, pFile ) != 1) { return 0; } // 写入文件所在位置 if ( /*fwrite*/_Encoderfwrite( &sFileInfo.nPos, sizeof(UINT), 1, pFile ) != 1 ) { return 0; } // 写入文件大小 if ( /*fwrite*/_Encoderfwrite( &sFileInfo.nFileSize, sizeof(UINT), 1, pFile ) != 1) { return 0; } // 写入文件压缩前的大小 if ( fwrite(&sFileInfo.nFileOrgSize,sizeof(UINT), 1, pFile ) !=1 ) { return 0; } return ftell( pFile ); } //////////////////////////////////////////////////////////////////////////////// //函数名:ReadFileInfoFromPackage //功能:从指定文件读取文件信息 //入口参数: FILE* pFile 源文件流指针 // SPackageFileInfo& sFileInfo 目标文件信息 // UINT nPos 读入位置 返回读入最后位置 //出口参数: bool 成功返回ture 失败返回 false //////////////////////////////////////////////////////////////////////////////// bool CPackageFileSystem::_ReadFileInfoFromPackage( FILE* pFile, SPackageFileInfo& sFileInfo, UINT& nPos ) { if (NULL == pFile) { return false; } // 偏移读指针到指定位置 fseek( pFile, nPos, SEEK_SET ); // 路径字符串长度 UINT nLen ; /*fread*/_Decoderfread( &nLen, sizeof(UINT), 1, pFile ); if ( feof(pFile) ) { return false; } //'\0'占一位 char *pChar = new char[nLen+1]; if ( NULL == pChar ) { ERROR_PRINT("申请内存失败:PACKAGEFILESYSTEM.CPP-_ReadFileInfoFromPackage",sFileInfo.szFullPathName.c_str()); return false; } if ( !fgets( pChar, nLen+1, pFile ) ) { delete [] pChar; pChar = NULL; return false; } string strIn = string(pChar); sFileInfo.szFullPathName = strIn; sFileInfo.szFilename = strIn.substr( strIn.find_last_of("\\") + 1 ); /*fread*/_Decoderfread( &sFileInfo.eFileType, sizeof(UINT), 1, pFile ); if ( feof(pFile) ) { delete [] pChar; pChar = NULL; return false; } /*fread*/_Decoderfread( &sFileInfo.eEncryptType, sizeof(UINT), 1, pFile ); if ( feof(pFile) ) { delete [] pChar; pChar = NULL; return false; } /*fread*/_Decoderfread( &sFileInfo.nPos, sizeof(UINT), 1, pFile ); if ( feof(pFile) ) { delete [] pChar; pChar = NULL; return false; } /*fread*/_Decoderfread( &sFileInfo.nFileSize, sizeof(UINT), 1, pFile ); if( feof(pFile) ) { delete [] pChar; pChar = NULL; return false; } fread( &sFileInfo.nFileOrgSize, sizeof(UINT), 1, pFile ); if ( ferror(pFile) ) { delete [] pChar; pChar = NULL; return false; } delete [] pChar; pChar = NULL; nPos = ftell(pFile); return true; } ////////////////////////////////////////////////////////////////////////////////// ////函数名:AddIdleSpace ////功能:添加一个碎片空间描述信息 ////入口参数: SPackageIdleSpaceInfo& sIdleInfo 源碎片空间信息 ////出口参数: bool ////说明: ////////////////////////////////////////////////////////////////////////////////// //bool CPackageFileSystem::_AddIdleSpace( SPackageIdleSpaceInfo& sIdleInfo ) //{ // /*if (m_bModified == false) // { // ERROR_PRINT("只读模式不可修改信息系统:PACKAGEFILESYSTEM.CPP-_AddIdleSpace"); // return false; // }*/ // for ( UINT uiIndex = 0; uiIndex < m_vIdleSpace.size(); uiIndex++ ) // { // if ( m_vIdleSpace[uiIndex].nPos == sIdleInfo.nPos ) // { // ERROR_PRINT("添加的碎片空间信息位置(nPos)已存在:PACKAGEFILESYSTEM.CPP-_AddIdleSpace",NULL); // return false; // } // } // // m_vIdleSpace.push_back( sIdleInfo ); // return true; //} ////////////////////////////////////////////////////////////////////////////////// ////函数名:DeleteIdleSpace ////功能:删除一个碎片空间描述信息 ////入口参数: SPackageIdleSpaceInfo sIdleInfo 源碎片空间信息 ////出口参数: bool ////说明: ////////////////////////////////////////////////////////////////////////////////// //bool CPackageFileSystem::_DeleteIdleSpace( SPackageIdleSpaceInfo sIdleInfo ) //{ // if (m_bModified == false) // { // ERROR_PRINT("只读模式不可修改信息系统:PACKAGEFILESYSTEM.CPP-_DeleteIdleSpace",NULL); // return false; // } // for ( vector::iterator it = m_vIdleSpace.begin(); it != m_vIdleSpace.end(); it++ ) // { // if ( it->nPos == sIdleInfo.nPos ) // { // m_vIdleSpace.erase(it); // MESSAGE_PRINT("碎片空间信息删除成功"); // return true; // } // } // // ERROR_PRINT("未找到指定碎片空间:PACKAGEFILESYSTEM.CPP-_DeleteIdleSpace",NULL); // return false; //} ////////////////////////////////////////////////////////////////////////// void CPackageFileSystem::GetAllFilesInfo(vector& vFileInfos) { _InsertAllFileInfoToVector(vFileInfos); } // [4/7/2009 hemeng] size_t CPackageFileSystem::_Encoderfwrite( const void *buffer, size_t size, size_t count,FILE *stream ) { // [4/7/2009 hemeng] // 添加文件信息加密代码,暂时不使用 //if (buffer == NULL) //{ // return -1; //} //// 加密 //BYTE* pTempBuffer = new BYTE[size]; //memcpy_s(pTempBuffer,size, buffer,size); // //if (!CSimpleEncoderBuffer::ConvertBuffer((BYTE*)buffer,size,pTempBuffer,size)) //{ // ERROR_PRINT("加密出错:PACKAGEFILESYSTEM.CPP-_Encoderfwrite",NULL); // delete [] pTempBuffer; // pTempBuffer = NULL; // return -1; //} //size_t iError = fwrite(pTempBuffer,size,count,stream); //delete [] pTempBuffer; //pTempBuffer = NULL; // //return iError; return fwrite(buffer,size,count,stream); } // [4/7/2009 hemeng] size_t CPackageFileSystem::_Decoderfread(void *buffer, size_t size, size_t count,FILE *stream ) { // [4/7/2009 hemeng] // 添加文件信息加密,暂时不使用 // 解密 //BYTE* pTempBuffer = new BYTE[size]; //size_t iError = fread(pTempBuffer,size,count,stream); //if ( ferror(stream) ) //{ // delete [] pTempBuffer; // pTempBuffer = NULL; // return iError; //} // //memcpy_s(buffer,size,pTempBuffer,size); //// 解密 //if (!CSimpleEncoderBuffer::ConvertBuffer(pTempBuffer,size,(BYTE*)buffer,size)) //{ // ERROR_PRINT("解密出错:PACKAGEFILESYSTEM.CPP-_Decoderfread",NULL); // delete [] pTempBuffer; // pTempBuffer = NULL; // return -1; //} //delete [] pTempBuffer; //pTempBuffer = NULL; //return iError; return fread(buffer,size,count,stream); }