面对上面情况,本人想到了内存机制:
如果中间结果数据不超过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];
}