#ifndef _CACHE_FILE_H_ #define _CACHE_FILE_H_ #pragma once #include <stdio.h> #include <map> using std::map; typedef struct tagStCacheData { unsigned char* m_ucBuffer; int m_iBufSize; int m_iCurPos; }StCacheData; typedef struct tagStCacheFile { FILE* m_fp; StCacheData m_stCacheData; char m_szName[256]; }StCacheFile; class CSzLess { public: bool operator()(const char* rht, const char* lht) const; }; class CCacheFile { public: CCacheFile(void); public: ~CCacheFile(void); int ClearCache(void); StCacheFile* Insert(const char* str, int size); int ReadData(StCacheFile* pstCacheFile, unsigned char* buf, int size); StCacheFile* OpenFile(const char* str); void CloseFile(StCacheFile* stCacheFile); bool IsCached(int size); int GetSize(void); static int GetFileSize(const char* str); private: map<char*, StCacheData, CSzLess> m_mapNameToCacheData; int m_iTotalBufferSize; int m_iUsedBufferSize; int m_iMaxFileSize; }; #endif #include "CacheFile.h" #include <string.h> #include <stdlib.h> #include <utility> using std::pair; bool CSzLess::operator()(const char *rht, const char *lht) const { if (NULL == rht || NULL == lht) { return false; } if (strcmp(rht, lht) < 0) { return true; } return false; } CCacheFile::CCacheFile(void) : m_iTotalBufferSize(100 * 1024 * 1024), m_iUsedBufferSize(0), m_iMaxFileSize(10 * 1024 * 1024) { } CCacheFile::~CCacheFile(void) { } int CCacheFile::ClearCache(void) { int iRet = 0; typedef map<char*, StCacheData, CSzLess>::iterator mapIterator; char* first = NULL; unsigned char* ucBuf = NULL; for (mapIterator ite = m_mapNameToCacheData.begin(); ite != m_mapNameToCacheData.end(); ite++) { first = ite->first; ucBuf = ite->second.m_ucBuffer; free(first); free(ucBuf); iRet++; } m_mapNameToCacheData.clear(); return iRet; } /* 返回 -1 文件打开失败, str == NULL */ int CCacheFile::GetFileSize(const char* str) { int iRet = -1; if (str != NULL) { FILE* fp = NULL; fp = fopen(str, "rb"); if (fp != NULL) { fseek(fp, 0, SEEK_END); iRet = (int)ftell(fp); fclose(fp); } } return iRet; } bool CCacheFile::IsCached(int size) { if (size > m_iMaxFileSize) { return false; } if (m_iUsedBufferSize + size <= m_iTotalBufferSize) { m_iUsedBufferSize += size; return true; } return false; } /* */ StCacheFile* CCacheFile::Insert(const char* str, int size) { StCacheFile* stRet = NULL; if (str != NULL && size >= 0) { stRet = (StCacheFile*)malloc(sizeof(StCacheFile)); memset(stRet, 0, sizeof(StCacheFile)); typedef map<char*, StCacheData, CSzLess>::value_type mapValueType; typedef map<char*, StCacheData, CSzLess>::iterator mapIterator; pair<mapIterator, bool> mapPair; mapIterator ite = m_mapNameToCacheData.find((char*)str); if (ite == m_mapNameToCacheData.end()) { char* ptr = strdup(str); StCacheData stCacheData; memset(&stCacheData, 0, sizeof(StCacheData)); stCacheData.m_iBufSize = size; stCacheData.m_iCurPos = 0; stCacheData.m_ucBuffer = (unsigned char*)malloc(size + 1); FILE* fp = NULL; fp = fopen(str, "rb"); if (fp != NULL) { if (stCacheData.m_ucBuffer != NULL) { fread(stCacheData.m_ucBuffer, 1, size, fp); } fclose(fp); } mapPair = m_mapNameToCacheData.insert(mapValueType(ptr, stCacheData)); ite = mapPair.first; } if (stRet != NULL) { stRet->m_stCacheData = ite->second; strncpy(stRet->m_szName, str, sizeof(stRet->m_szName) - 1); } } return stRet; } StCacheFile* CCacheFile::OpenFile(const char* str) { StCacheFile* stRet = NULL; int size = GetFileSize(str); if (size != -1) { if (IsCached(size)) { stRet = Insert(str, size); } else { stRet = (StCacheFile*)malloc(sizeof(StCacheFile)); memset(stRet, 0, sizeof(StCacheFile)); if (stRet != NULL) { stRet->m_fp = fopen(str, "rb"); strncpy(stRet->m_szName, str, sizeof(stRet->m_szName) - 1); } } } return stRet; } void CCacheFile::CloseFile(StCacheFile* stCacheFile) { if (stCacheFile != NULL) { if (stCacheFile->m_fp != NULL) { fclose(stCacheFile->m_fp); } else { typedef map<char*, StCacheData, CSzLess>::iterator mapIterator; mapIterator ite = m_mapNameToCacheData.find(stCacheFile->m_szName); if (ite != m_mapNameToCacheData.end()) { char* frist = NULL; unsigned char* ucBuf = NULL; frist = ite->first; ucBuf = ite->second.m_ucBuffer; m_iUsedBufferSize -= ite->second.m_iBufSize; free(frist); free(ucBuf); m_mapNameToCacheData.erase(ite); } } free(stCacheFile); } } int CCacheFile::GetSize(void) { return m_mapNameToCacheData.size(); } int CCacheFile::ReadData(StCacheFile* pstCacheFile, unsigned char* buf, int size) { return 0; }