CAnsiMemFile的使用非常简单,只用把下面的代码保存到一个AnsiMemFile.h头文件中(这个类没有CPP文件),然后在你的VC工程中#include "AnsiMemFile.h"就可以了。该类的接口和MF的CMemFile类基本一致,可以参考MSDN中CMemFile类的文档。
// AnsiMemFile.h: the CAnsiMemFile class.
//
// A memory file class without MFC
// Version: 1.0
// Data: 2005-10-27
//
// www.farproc.com
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ANSIMEMFILE_H__2F568214_9834_4B67_B97E_FFB21CDB61F1__INCLUDED_)
#define AFX_ANSIMEMFILE_H__2F568214_9834_4B67_B97E_FFB21CDB61F1__INCLUDED_
#include
#include
#include
#include
#include
class CAnsiMemFile
{
protected:
UINT m_nGrowBytes;
DWORD m_nPosition;
DWORD m_nBufferSize;
DWORD m_nFileSize;
BYTE* m_lpBuffer;
BOOL m_bAutoDelete;
BYTE* Alloc(DWORD nBytes)
{
return (BYTE*)malloc((UINT)nBytes);
}
BYTE* Realloc(BYTE* lpMem, DWORD nBytes)
{
return (BYTE*)realloc(lpMem, (UINT)nBytes);
}
#pragma intrinsic(memcpy)
BYTE* Memcpy(BYTE* lpMemTarget, const BYTE* lpMemSource,
UINT nBytes)
{
assert(lpMemTarget != NULL);
assert(lpMemSource != NULL);
//assert(AfxIsValidAddress(lpMemTarget, nBytes));
//assert(AfxIsValidAddress(lpMemSource, nBytes, FALSE));
return (BYTE*)memcpy(lpMemTarget, lpMemSource, nBytes);
}
#pragma function(memcpy)
void Free(BYTE* lpMem)
{
assert(lpMem != NULL);
free(lpMem);
}
void GrowFile(DWORD dwNewLen)
{
assert(this);
if (dwNewLen > m_nBufferSize)
{
// grow the buffer
DWORD dwNewBufferSize = (DWORD)m_nBufferSize;
// watch out for buffers which cannot be grown!
assert(m_nGrowBytes != 0);
//if (m_nGrowBytes == 0)
// AfxThrowMemoryException();
// determine new buffer size
while (dwNewBufferSize < dwNewLen)
dwNewBufferSize += m_nGrowBytes;
// allocate new buffer
BYTE* lpNew;
if (m_lpBuffer == NULL)
lpNew = Alloc(dwNewBufferSize);
else
lpNew = Realloc(m_lpBuffer, dwNewBufferSize);
if (lpNew == NULL)
//AfxThrowMemoryException();
throw exception("分配内存错误!");
m_lpBuffer = lpNew;
m_nBufferSize = dwNewBufferSize;
}
assert(this);
}
public:
enum SeekPosition { begin = 0x0, current = 0x1, end = 0x2 };
//nGrowBytes 该文件需要增大时的增大粒度(每次增大nGrowBytes个字节)
CAnsiMemFile(UINT nGrowBytes = 1024)
{
assert(nGrowBytes <= UINT_MAX);
m_nGrowBytes = nGrowBytes;
m_nPosition = 0;
m_nBufferSize = 0;
m_nFileSize = 0;
m_lpBuffer = NULL;
m_bAutoDelete = TRUE;
}
//相对于构造后调用Attach
CAnsiMemFile(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes = 0)
{
assert(nGrowBytes <= UINT_MAX);
m_nGrowBytes = nGrowBytes;
m_nPosition = 0;
m_nBufferSize = nBufferSize;
m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
m_lpBuffer = lpBuffer;
m_bAutoDelete = FALSE;
}
~CAnsiMemFile()
{
// Close should have already been called, but we check anyway
if (m_lpBuffer)
Close();
assert(m_lpBuffer == NULL);
m_nGrowBytes = 0;
m_nPosition = 0;
m_nBufferSize = 0;
m_nFileSize = 0;
}
//////////////////////取属性
//取得当前读写位置
DWORD GetPosition() const
{
assert(this);
return m_nPosition;
}
//取得文件的当前大小
DWORD GetLength() const
{
DWORD dwLen, dwCur;
// Seek is a non const operation
CAnsiMemFile* pFile = (CAnsiMemFile*)this;
dwCur = pFile->Seek(0L, current);
dwLen = pFile->SeekToEnd();
pFile->Seek(dwCur, begin);
return dwLen;
}
//取得内存数据指针
//注意:只读,不要修改该指针指向的内容。如果需要读写该文件内容,请用Read()和Write()
const BYTE const * GetPtr() const
{
return m_lpBuffer;
}
///////////////////////操作
//指定本文件所用的内存
//该对象析构时不会释放改内存块
void Attach(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
{
assert(m_lpBuffer == NULL);
m_nGrowBytes = nGrowBytes;
m_nPosition = 0;
m_nBufferSize = nBufferSize;
m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
m_lpBuffer = lpBuffer;
m_bAutoDelete = FALSE;
}
//解除该文件和它当前占用的内存块的关联
//返回该内存块的指针
BYTE* Detach()
{
BYTE* lpBuffer = m_lpBuffer;
m_lpBuffer = NULL;
m_nFileSize = 0;
m_nBufferSize = 0;
m_nPosition = 0;
return lpBuffer;
}
//移动读写位置到文件最后
DWORD SeekToEnd()
{
return Seek(0, CAnsiMemFile::end);
}
//移动读写位置到文件开头
void SeekToBegin()
{
Seek(0, CAnsiMemFile::begin);
}
//改变文件长度
//如果需要会重新分配所占内存
void SetLength(DWORD dwNewLen)
{
assert(this);
if (dwNewLen > m_nBufferSize)
GrowFile(dwNewLen);
if (dwNewLen < m_nPosition)
m_nPosition = dwNewLen;
m_nFileSize = dwNewLen;
assert(this);
}
//从当前读写位置读取指定长度的数据
UINT Read(void* lpBuf, UINT nCount)
{
assert(this);
if (nCount == 0)
return 0;
assert(lpBuf != NULL);
//assert(AfxIsValidAddress(lpBuf, nCount));
if (m_nPosition > m_nFileSize)
return 0;
UINT nRead;
if (m_nPosition + nCount > m_nFileSize)
nRead = (UINT)(m_nFileSize - m_nPosition);
else
nRead = nCount;
Memcpy((BYTE*)lpBuf, (BYTE*)m_lpBuffer + m_nPosition, nRead);
m_nPosition += nRead;
assert(this);
return nRead;
}
//写指定长度的数据到文件内
void Write(const void* lpBuf, UINT nCount)
{
assert(this);
if (nCount == 0)
return;
assert(lpBuf != NULL);
//assert(AfxIsValidAddress(lpBuf, nCount, FALSE));
if (m_nPosition + nCount > m_nBufferSize)
GrowFile(m_nPosition + nCount);
assert(m_nPosition + nCount <= m_nBufferSize);
Memcpy((BYTE*)m_lpBuffer + m_nPosition, (BYTE*)lpBuf, nCount);
m_nPosition += nCount;
if (m_nPosition > m_nFileSize)
m_nFileSize = m_nPosition;
assert(this);
}
//移动读写位置
//lOff 移动的距离
//nFrom 指定从哪里开始移动
//
//第二个参数可以为:
//enum SeekPosition { begin = 0x0, current = 0x1, end = 0x2 };
LONG Seek(LONG lOff, UINT nFrom)
{
assert(this);
assert(nFrom == begin || nFrom == end || nFrom == current);
LONG lNewPos = m_nPosition;
if (nFrom == begin)
lNewPos = lOff;
else if (nFrom == current)
lNewPos += lOff;
else if (nFrom == end)
lNewPos = m_nFileSize + lOff;
else
return -1;
if (lNewPos < 0)
throw exception("Seek错误");
m_nPosition = lNewPos;
assert(this);
return m_nPosition;
}
//关闭内存文件,释放所占用的内存,置长度为0。
//该内存文件不可增长(即不可再写入任何数据)
//析构函数会自动调用Close
void Close()
{
assert((m_lpBuffer == NULL && m_nBufferSize == 0) ||
!m_bAutoDelete || TRUE);
assert(m_nFileSize <= m_nBufferSize);
m_nGrowBytes = 0;
m_nPosition = 0;
m_nBufferSize = 0;
m_nFileSize = 0;
if (m_lpBuffer && m_bAutoDelete)
Free(m_lpBuffer);
m_lpBuffer = NULL;
}
};
/////////////////////////////////////////////////////////////////////////////
#endif // !defined(AFX_ANSIMEMFILE_H__2F568214_9834_4B67_B97E_FFB21CDB61F1__INCLUDED_)
下面是一个使用这个类的简单例子(Win32 Console):
// AnsiMemFilePrj.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "AnsiMemFile.h"
int main(int argc, char* argv[])
{
CAnsiMemFile file;
printf("******** BEFORE ********/n");
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
printf("SeekToBegin: /n");
file.SeekToBegin();
printf("SeekToEnb: %d/n", file.SeekToEnd());
printf("Seek 100 from begin: %d/n", file.Seek(100, CAnsiMemFile::begin));
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
char szData[] = "123456789abcde";
printf("Write a string %s to file:/n", szData);
file.Write(szData, strlen(szData));
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
printf("Seek to begin:/n");
file.SeekToBegin();
memset(szData, 0, strlen(szData));
printf("Read from file: %d/n |%s|/n", file.Read(szData, 14), szData);
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
printf("Seek to end:/n");
file.SeekToEnd();
memset(szData, 0, strlen(szData));
printf("Read from file: %d/n |%s|/n", file.Read(szData, 14), szData);
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
printf("Seek to 100 from begin:/n");
file.Seek(100, CAnsiMemFile::begin);
memset(szData, 0, strlen(szData));
printf("Try to read 14 bytes from file: %d bytes actually read/n |%s|/n", file.Read(szData, 14), szData);
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
//如果添加该代码,则下面的代码会出错
//因为文件关闭后即不能再使用
/*printf("*********** CLOSE ***********/n");
printf("Close() is called.../nAfter close:/n");
file.Close();
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
*/
printf("SetLength to 5:/n");
file.SetLength(5);
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
printf("Seek to begin:/n");
file.SeekToBegin();
printf("Write a string %s (with 0) to file:/n", szData);
file.Write(szData, strlen(szData) + 1);
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
printf("GetPtr() returns 0x%x. The string is |%s|/n/n", file.GetPtr(), file.GetPtr());
printf("Close() is called.../nAfter close:/n");
file.Close();
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
printf("Seek to 56635 form end/n");
file.Seek(65535, CAnsiMemFile::end);
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
memset(szData, 0, strlen(szData));
printf("Try to read 14 bytes from file: %d bytes actually read/n |%s|/n", file.Read(szData, 14), szData);
printf(">> Length = %d/n", file.GetLength());
printf(">> Position = %d/n", file.GetPosition());
printf(">>Ptr = %x/n/n", file.GetPtr());
return 0;
}