头文件:
//MemTextFile.h
#pragma once
class CMemTextFile
{
public:
CMemTextFile(void);
~CMemTextFile(void);
public:
BOOL OpenFile(IN LPCTSTR lpPath);
BOOL ReadString(IN OUT LPTSTR& lpBufferString);
void CloseFile();
DWORD GetFileSize();
private:
HANDLE m_hFile;
HANDLE m_hFileMap;
PBYTE m_lpbFile;
DWORD m_dwFileSize;
DWORD m_dwLastPos;
TCHAR *m_pBuffer;
DWORD m_dwBufferSize;
BOOL m_bIsMalloc;
};
源文件:
//MemTextFile.cpp
#include "StdAfx.h"
#include <Shlwapi.h>
#pragma comment(lib,"Shlwapi.lib")
#include "MemTextFile.h"
#define DEF_MEM_INC 100
CMemTextFile::CMemTextFile(void)
{
}
CMemTextFile::~CMemTextFile(void)
{
CloseFile();
}
BOOL CMemTextFile::OpenFile( IN LPCTSTR lpPath )
{
m_hFile=INVALID_HANDLE_VALUE;
m_hFileMap=NULL;
m_lpbFile=NULL;
m_dwFileSize=0;
m_dwLastPos=0;
m_dwBufferSize=DEF_MEM_INC;
m_pBuffer=NULL;
m_bIsMalloc=FALSE;
if (!PathFileExists(lpPath))
{
return FALSE;
}
m_hFile=CreateFile(
lpPath,//路径
GENERIC_READ,//读
FILE_SHARE_READ,//共享类型只读
NULL,//文件的安全特性
OPEN_EXISTING,//文件必须已经存在
FILE_FLAG_SEQUENTIAL_SCAN,//针对连续访问对文件缓冲进行优化
NULL);//如果不为零,则指定一个文件句柄
if (INVALID_HANDLE_VALUE==m_hFile)
{
return FALSE;
}
m_dwFileSize=::GetFileSize(m_hFile,NULL);
m_hFileMap = CreateFileMapping(m_hFile,
NULL, //安全对象
PAGE_READONLY,//以只读方式打开映射
0,
0, //用磁盘文件的实际长度
NULL);//指定文件映射对象的名字
if (NULL==m_hFileMap)
{
return FALSE;
}
m_lpbFile = (PBYTE) MapViewOfFile(
m_hFileMap,
FILE_MAP_READ,
0,
0, //映射整个文件映射对象
0);//零表示允许windows寻找地址
if (NULL==m_lpbFile)
{
return FALSE;
}
return TRUE;
}
void CMemTextFile::CloseFile()
{
if (m_lpbFile!=NULL)
{
UnmapViewOfFile(m_lpbFile);
}
if (m_hFileMap!=NULL)
{
CloseHandle(m_hFileMap);
}
if (m_hFile!=INVALID_HANDLE_VALUE)
{
CloseHandle(m_hFile);
}
m_hFile=INVALID_HANDLE_VALUE;
m_hFileMap=NULL;
m_lpbFile=NULL;
m_dwFileSize=0;
m_dwLastPos=0;
m_bIsMalloc=FALSE;
if (m_pBuffer!=NULL)
{
free(m_pBuffer);
m_pBuffer=NULL;
}
m_dwBufferSize=0;
}
BOOL CMemTextFile::ReadString(IN OUT LPTSTR& lpBufferString)
{
if (NULL==m_lpbFile)
{
return FALSE;
}
if (m_dwLastPos>=(m_dwFileSize-1))
{
return FALSE;
}
if (!m_bIsMalloc)
{
m_pBuffer=(TCHAR*)malloc(m_dwBufferSize*sizeof(TCHAR));
if (m_pBuffer==NULL)
{
return FALSE;
}
m_bIsMalloc=TRUE;
}
memset(m_pBuffer,0,m_dwBufferSize*sizeof(TCHAR));
DWORD dwCount=0;
while(m_dwLastPos<(m_dwFileSize-1))
{
if (m_lpbFile[m_dwLastPos]=='\r')//回车CR
{
++m_dwLastPos;
if (m_dwLastPos<(m_dwFileSize-1))
{
if (m_lpbFile[m_dwLastPos]=='\n')//回车后紧接着是换行CR LF
{
++m_dwLastPos;
}
}
break;
}
else if (m_lpbFile[m_dwLastPos]=='\n')//换行LF
{
++m_dwLastPos;
break;
}
if (dwCount>=m_dwBufferSize)
{
m_pBuffer=(TCHAR*)realloc(m_pBuffer,(m_dwBufferSize+DEF_MEM_INC)*sizeof(TCHAR));
if (m_pBuffer==NULL)
{
return FALSE;
}
memset(m_pBuffer+m_dwBufferSize,0,DEF_MEM_INC*sizeof(TCHAR));
m_dwBufferSize=m_dwBufferSize+DEF_MEM_INC;
}
m_pBuffer[dwCount++]=(TCHAR)(m_lpbFile[m_dwLastPos]);
++m_dwLastPos;
}
m_pBuffer[dwCount++]='\n';
m_pBuffer[dwCount++]='\r';
lpBufferString=m_pBuffer;
return TRUE;
}
DWORD CMemTextFile::GetFileSize()
{
return m_dwFileSize;
}
使用方法:
CMemTextFile txt;
if (!txt.OpenFile(_T("Bigtest2.nc")))
{
AfxMessageBox(_T("打开文件失败!!"));
}
TCHAR *szLine=NULL;
while(txt.ReadString(szLine))
{
//TRACE("szLine=%s\n",szLine);
}
txt.CloseFile();
性能比较:
硬件环境为E5200CPU,2G内存。
测试文件为40M,200万行的文本文件。
使用CMemTextFile,用时653ms。
使用CStdioFile,用时4120ms。
时间用指令RDTSC测得:
__asm
{
_emit 0x0F;
_emit 0x31;
}
|