内存中模拟目录和文件,软件资源保护新办法

项目中常常需要将中间结果进行保存, 以供后续步骤进行处理. 如果以临时文件的方式往往容易"暴露"中间机密信息. 同时,文件IO读写也较浪费时间(说到这里,不得不BS一下windows的文件系统,当一个目录下的文件数目超过10000时,读写文件相当慢,Linux却没有这样的问题). 

    面对上面情况,本人想到了内存机制: 

   

  如果中间结果数据不超过2G(32位windows的内存地址上限).可以在内存中模拟一个文件系统.将这些信息以"内存文件"形式保存在"内存",同时也能提供"内存目录"(或"内存Db")支持. 


    下面是"内存文件类"的使用示例(使用上和一般的文件类没任何区别,只是不在磁盘上生成文件): 

    CMemoryFile pfile; 

    pfile.fopen( "c:/www/1235.bxk", "wb" ); 

    pfile.fprintf( "aaa\nbbb\n" ); 

    pfile.fclose(); 

    CMemoryFile pfile0; 

    pfile0.fopen( "c:/www/1234.bxk", "wb" ); 

    pfile0.fprintf( "aaa\nbbb\n" ); 

    pfile0.fclose(); 


    // 删除文件"1234.bxk" 

    bool bRs = RemoveMemDbfile( "c:/www/1234.bxk" ); 

    RemoveMemDbfile( "c:/www/1235.bxk" ); 

    ASSERT( bRs ); 

    // 遍历内存目录"c:/www"下的所有文件(输出文件名). 

    CBlockIter blkIter( "c:/www" ); 

    while ( blkIter.next() ) 

    { 

    char szfn[256]; 

    blkIter.getBlockFn( szfn ); 

    printf( "file:%s", szfn ); 

    } 

    // 按行读取"1235.bxk"下的内容. 

    CMemoryFile pfile1; 

    pfile1.fopen( "c:/www/1235.bxk", "rb" ); 

    char szline[256]; 

    while ( pfile1.fgets(szline, sizeof(szline))) 

    { 

        printf("%s", szline); 

    } 

    pfile1.fclose(); 

使用上是不是相当easy? 其实实现起来也不复杂,出于下面目的所以拿出来共享:一方便如果能为您节省一点点开发时间,本人将非常高兴;另一方面,提高水平的方式是"晒代码",有啥批抨的尽量提,洗耳恭听! 

具何实现: 

// MemoryFile.h: interface for the CMemoryFile class. 

// 

// 

#if !defined(AFX_MEMORYFILE_H__0A6B4842_05D3_4B2A_A1EC_BAF340135266__INCLUDED_) 

#define AFX_MEMORYFILE_H__0A6B4842_05D3_4B2A_A1EC_BAF340135266__INCLUDED_ 

#if _MSC_VER > 1000 

#pragma once 

#endif // _MSC_VER > 1000 

#include  

#include  

#include  

#include  

#include  

#define ASSERT assert 

//#define pprintf printf 

#define pprintf 

const char* safe_strtok(const char* sz, 

                        const char* szToken, std::string& str); 

class CMemoryDb; 

class CGlobalMan 


public: 

    std::map mapName2MemDb; 

    

    CGlobalMan() 

    { 

    } 

    virtual ~CGlobalMan(); 

}; 

extern CGlobalMan* g_pGlobal; 

// [内存"磁盘"]:模拟一个目录 

// 对外接口: 

// 1.根据文件名,往[内存"磁盘"]读写文件. 

// 2.可以删除[内存"磁盘"]内的某个文件。 

// 3.可遍历[内存"磁盘"]内的所有文件名(同时获取文件属性m_nSegCnt和m_nNodCnt)。 

// 4.根据目录名,可创建或查找[内存"磁盘"]。 

typedef struct tagFINFO 


    char    szfn[64]; 

    int        nlen; 

    int        scnt; 

    int        ncnt; 

    void*    pdata; 

    tagFINFO() 

    { 

        memset( szfn, 0, sizeof(szfn) ); 

        nlen = 0; 

        scnt = 0; 

        ncnt = 0; 

        pdata= NULL; 

    } 

}FINFO; 

class CMemoryDb 


    std::map mapFn2Content; 

    std::map::iterator m_it; 

public: 

    CMemoryDb() 

    { 

        pprintf("CMemoryDb()"); 

    } 

    virtual ~CMemoryDb(); 

    // 读写文件 

    void* FindFile( const char fn[], int* nLen ) 

    { 

        if (nLen) *nLen = 0; 

        if ( mapFn2Content.find(fn) == mapFn2Content.end() ) 

            return NULL; 

        FINFO& pinfo = mapFn2Content[fn]; 

        if (nLen) *nLen = pinfo.nlen; 

        return &pinfo; 

    } 

    void* CreateFile( const char fn[], const int nLen ) 

    { 

        // nLen为零:外部分配内存(目前只支持这种), pRet->pdata == NULL 

        ASSERT( nLen == 0 ); 

        FINFO item; 

        strcpy( item.szfn, fn ); 

        mapFn2Content[fn] = item; 

        return &(mapFn2Content[fn]); 

    } 

    // 删除文件 

    bool DeleteFile( const char fn[] ) 

    { 

        if ( mapFn2Content.find(fn) != mapFn2Content.end() ) 

        { 

            delete mapFn2Content[fn].pdata; 

            mapFn2Content.erase( fn ); 

            return true; 

        }        

        return false; 

    } 

    // 遍历 

    bool Begin_DbItem() 

    { 

        m_it = mapFn2Content.begin(); 

        return true; 

    } 

    

    bool Next_DbItem() 

    { 

        bool bret = ( m_it != mapFn2Content.end() ); 

        if ( bret ) m_it ++; 

        return bret; 

    } 

    void* Get_DbItem() 

    { 

        if ( m_it == mapFn2Content.end() ) 

            return NULL; 

        return &(m_it->second); 

    } 

public: 

    // 查找或创建[内存"磁盘"] 

    static CMemoryDb* MemDbLookup( const char* dbname ) 

    { 

        if ( g_pGlobal->mapName2MemDb.find( dbname ) == 

            g_pGlobal->mapName2MemDb.end()) 

            return NULL; 

        return (CMemoryDb*)g_pGlobal->mapName2MemDb[dbname];    

    } 

    static CMemoryDb* CreateMemDb( const char* dbname ) 

    { 

        CMemoryDb* pDb = MemDbLookup(dbname); 

        if(pDb) return pDb; 

        

        pDb = new CMemoryDb; 

        

        ASSERT( g_pGlobal->mapName2MemDb.find( dbname ) == 

            g_pGlobal->mapName2MemDb.end() ); 

        g_pGlobal->mapName2MemDb[dbname] = pDb; 

        

        return pDb; 

    } 

    

private: 

    

}; 

// MemDb文件枚举类 

class CBlockIter 


private: 

    CMemoryDb            *m_pMDb; 

    bool                m_bReady; 

    std::vector  m_vctBlks; 

    int                    m_index; 

public: 

    CBlockIter( const char* db_name ):m_pMDb(NULL), 

        m_bReady(true), m_index(-1) 

    { 

        m_pMDb = CMemoryDb::MemDbLookup( db_name ); 

        if ( !m_pMDb ) 

        { 

            ASSERT(0); 

            m_bReady = false; 

            return; 

        } 

        m_vctBlks.clear(); 

        FINFO* pfinf = NULL; 

        m_pMDb->Begin_DbItem();        

        while ( pfinf = (FINFO*)m_pMDb->Get_DbItem() ) 

        {    

            m_vctBlks.push_back( *pfinf ); 

            m_pMDb->Next_DbItem(); 

        } 

        finalize(); 

    } 

    virtual ~CBlockIter() 

    { 

        finalize(); 

    } 

    bool    next() 

    { 

        if ( !m_bReady ) return false;        

        m_index ++;        

        if ( m_index == (int)m_vctBlks.size() ) return false;        

        return true; 

    } 

    int        getBlockFn( char fn[] ) 

    { 

        strcpy( fn, m_vctBlks[m_index].szfn ); 

        return 0; 

    } 

    int        getBlockId() 

    { 

        char* pszNum = m_vctBlks[m_index].szfn;        

        int r = 0; 

        if( pszNum ) 

            sscanf( pszNum, "%x", &r ); 

        return r; 

    } 

    int        getSegCnt() 

    { 

        return m_vctBlks[m_index].scnt; 

    } 

    int        getNodeCnt() 

    { 

        return m_vctBlks[m_index].ncnt; 

    } 

private: 

    void    finalize() 

    { 

        if ( m_pMDb ) m_pMDb = NULL;    

    } 

    

}; 

// [内存"磁盘"]文件 读写类 

// 对外接口: 

// 1.根据文件名,创建或打开内存文件。 

// 2.fgets或fprintf字符串读写,可写入文件属性m_nSegCnt和m_nNodCnt。 

typedef unsigned char BYTE; 

class CMemoryFile  

{    

    CMemoryDb* m_pMDb; 

    int      m_nSegCnt; 

    int    m_nNodCnt; 

    int      m_nIsRead;    

    int      m_nReadLen; 

    int      m_nOffset; 

    FINFO* m_pSream; 

    char  m_dbName[256];    

    std::string m_strData; 

public: 

    CMemoryFile():m_pMDb(NULL), m_nSegCnt(0), 

        m_nNodCnt(0), m_nIsRead(0), m_nReadLen(0), m_nOffset(0), m_pSream(NULL) 

    { 

    } 

    virtual ~CMemoryFile() 

    { 

        close(); 

    } 

    // added by wuwenwen 

    bool fopen( const char* fname, const char* mode ) 

    { 

        // 获取目录名,文件名 

        char szDirName[256]; 

        strcpy( szDirName, fname );        

        const char*  h = szDirName; 

        std::string  strFName;  

        h = safe_strtok(h, "/\\", strFName); 

        while (h) 

        { 

            h = safe_strtok(h, "/\\", strFName); 

        }    

        szDirName[ strlen(szDirName) - strFName.length() - 1 ] = ’\0’; 

        

        close(); 

        strcpy( m_dbName, szDirName ); 

        

        m_pMDb  = CMemoryDb::CreateMemDb( m_dbName ); 

        if ( !m_pMDb ) 

        { 

            return false; 

        } 

        if ( strcmp( mode, "wb" ) == 0 ) 

        { 

            m_nIsRead = 0; 

        } 

        else if ( strcmp( mode, "rb" ) == 0 ) 

        { 

            m_nIsRead = 1; 

        } 

        else 

        { 

            ASSERT(0); 

            return false; 

        } 

        if ( !m_nIsRead ) 

        {    

            pprintf("write\n"); 

            // 存在就先删掉 

            m_pSream = (FINFO*)m_pMDb->FindFile(strFName.c_str(), NULL); 

            if ( m_pSream ) 

            { 

                pprintf( "delete file:%s\n", strFName.c_str( ) ); 

                m_pMDb->DeleteFile(strFName.c_str()); 

            } 

            m_pSream = (FINFO*)m_pMDb->CreateFile(strFName.c_str(), 0); 

            

            m_strData.reserve( 6 * 1024 * 1024 ); 

        } 

        else 

        { 

            pprintf("read\n"); 

            // 文件存在? 

            m_pSream = (FINFO*)m_pMDb->FindFile(strFName.c_str(), &m_nReadLen); 

            if ( !m_pSream ) 

            { 

                ::fprintf( stdout, "read:%s,not existed\n", strFName.c_str() ); 

                return false; 

            }            

        } 

        

        return true; 

    } 

    int  fgets( char* line, int nsize ) 

    { 

        if ( !m_nIsRead ) return 0;    

        

        if( m_nOffset == m_nReadLen ) return 0; 

        char* pl = line;    

        char* pb = &(((char *)m_pSream->pdata)[ m_nOffset ]); 

        while( *pb == ’\n’ ) 

        { 

            pb ++; 

            m_nOffset ++; 

        } 

        if( m_nOffset == m_nReadLen ) return 0; 

        

        for( ; m_nOffset < m_nReadLen && 

            nsize && *pb != ’\n’; pb++, nsize -- ) 

        { 

            *pl++ = *pb; 

            m_nOffset++; 

        } 

        if ( (pl - line) &&  *pb == ’\n’ ) 

        { 

            *pl++ = ’\n’; 

            *pl  = ’\0’; 

        } 

        else 

        { 

            *pl = ’\0’; 

        }        

        return (int)(pl - line); 

    } 

    int  fprintf( const char* szFormat, ...  ) 

    { 

        if ( m_nIsRead ) return 0; 

        

        int done = 0; 

        

        char s[65000]; 

        va_list arg;        

        va_start (arg, szFormat); 

        done = vsprintf (s, szFormat, arg); 

        va_end (arg); 

        

        pprintf( "fprintf %s\n", s ); 

        m_strData += s;        

        return done; 

    } 

    bool fclose() 

    { 

        close(); 

        return true; 

    } 

    

    bool setcnt( int segcnt, int nodcnt ) 

    { 

        m_nSegCnt = segcnt;    

        m_nNodCnt = nodcnt;     

        return true; 

    } 

private: 

    bool close() 

    { 

        if ( !m_nIsRead ) flush(); 

        if(m_pMDb || m_pSream) 

        { 

            m_pMDb  = NULL; 

            m_pSream = NULL; 

        } 

        

        return true; 

    } 

    bool flush() 

    { 

        if ( !m_pSream || m_nIsRead || 

            m_strData.length() == 0 ) return false; 

        int nlen = m_strData.length(); 

        BYTE* pdata = new BYTE[nlen]; 

        memcpy( pdata, m_strData.c_str(), nlen ); 

        // 内部没分配内存 

        ASSERT( m_pSream->pdata == NULL ); 

        m_pSream->nlen  = nlen; 

        m_pSream->scnt  = m_nSegCnt; 

        m_pSream->ncnt  = m_nNodCnt; 

        m_pSream->pdata = pdata; 

        m_strData.erase(); 

    } 

    

}; 

bool RemoveMemDbfile( const char szfn[] ); 

#endif // !defined(AFX_MEMORYFILE_H__0A6B4842_05D3_4B2A_A1EC_BAF340135266__INCLUDED_) 

// MemoryFile.cpp: implementation of the CMemoryFile class. 

// 

// 

#include "stdafx.h" 

#include "MemoryFile.h" 

// 这里还要定义 

CGlobalMan g_Global; 

CGlobalMan* g_pGlobal = &g_Global; 

CMemoryDb::~CMemoryDb() 


    std::map::iterator it; 

    for ( it = mapFn2Content.begin(); 

    it != mapFn2Content.end(); it ++ ) 

    { 

        delete it->second.pdata; 

    } 

    

    pprintf("~CMemoryDb()\n"); 


CGlobalMan::~CGlobalMan() 


    // 全局析构 

    std::map::iterator it; 

    for ( it = mapName2MemDb.begin(); 

    it != mapName2MemDb.end(); it ++ ) 

    { 

        CMemoryDb* pmd = (CMemoryDb*)it->second; 

        delete pmd; 

    } 

    

    pprintf("~CGlobalMan()\n"); 


bool RemoveMemDbfile( const char szfn[] ) 


    // 获取目录名,文件名 

    char szDirName[256]; 

    strcpy( szDirName, szfn );        

    const char*  h = szDirName; 

    std::string  strFName;  

    h = safe_strtok(h, "/\\", strFName); 

    while (h) 

    { 

        h = safe_strtok(h, "/\\", strFName); 

    }    

    szDirName[ strlen(szDirName) - strFName.length() - 1 ] = ’\0’; 

    CMemoryDb* pmd = CMemoryDb::MemDbLookup( szDirName ); 

    if ( !pmd ) return false; 

    return pmd->DeleteFile( strFName.c_str() );    


const char* safe_strtok(const char* sz, const char* szToken, std::string& str) 


    int i = 0; 

    for( i=0; sz[i] != ’\0’; i++ ) 

    { 

        if ( strchr( szToken, sz[i] ) != NULL ) 

        { 

            break; 

        } 

    } 

    

    str = std::string( sz, i ); 

    return ( sz[i] == ’\0’ ) ? NULL : &sz[i+1]; 

你可能感兴趣的:(内存中模拟目录和文件,软件资源保护新办法)