项目中常常需要将中间结果进行保存, 以供后续步骤进行处理. 如果以临时文件的方式往往容易"暴露"中间机密信息. 同时,文件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 <stdarg.h>

#include <map>

#include <string>

#include <vector>

#include <assert.h>

#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<std::string, CMemoryDb*> 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<std::string, FINFO> mapFn2Content;

    std::map<std::string, FINFO>::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<FINFO>  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<std::string, FINFO>::iterator it;

    for ( it = mapFn2Content.begin();

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

    {

        delete it->second.pdata;

    }

   

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

}

CGlobalMan::~CGlobalMan()

{

    // 全局析构

    std::map<std::string, CMemoryDb*>::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];

}

Logo

更多推荐