There is a very useful cmemfile class in MFC, which allows us to operate a piece of memory like reading and writing files. But its biggest disadvantage is that it uses MFC and inherits from cobject, so that we cannot use this convenient memory file class when writing non-MFC programs. The following is a cansimemfile class that I have rewritten based on the source code of the cmemfile of MFC. I have removed the part of the cmemfile that uses MFC and hope it will be useful to you.
Cansimemfile is very simple to use. You only need to save the following code to an ansimemfile. h header file (this class does not have a CPP file), and then in your VC Project # include "ansimemfile. h. The interface of this class is basically the same as the cmemfile class of MF. You can refer to the document of the cmemfile class in msdn.
// 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_h1_2f568214_9834_4b67_b97e_ffb21cdb61f11_encoded _
# 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 ("Memory Allocation Error! ");
M_lpbuffer = lpnew;
M_nbuffersize = dwnewbuffersize;
}
Assert (this );
}
Public:
Enum seekposition {begin = 0x0, current = 0x1, end = 0x2 };
// Ngrowbytes increase the granularity of the file to be increased (each time ngrowbytes is increased)
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;
}
// Call attach after Construction
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 shoshould 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;
}
/// // Obtain the attribute
// Obtain the current read/write location
DWORD getposition () const
{
Assert (this );
Return m_nposition;
}
// Obtain the current file size
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;
}
// Obtain the Memory Data Pointer
// Note: Read-Only. do not modify the content pointed to by the pointer. To read and write the file content, use read () and write ()
Const byte const * getptr () const
{
Return m_lpbuffer;
}
/// // Operation
// Specify the memory used for this file
// The modified memory block is not released during the object structure analysis.
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;
}
// Unassociate the file from the memory block currently occupied by the file
// Returns the pointer of the memory block.
Byte * detach ()
{
Byte * lpbuffer = m_lpbuffer;
M_lpbuffer = NULL;
M_nfilesize = 0;
M_nbuffersize = 0;
M_nposition = 0;
Return lpbuffer;
}
// Move the read/write location to the end of the file
DWORD seektoend ()
{
Return seek (0, cansimemfile: End );
}
// Move the read/write location to the beginning of the file
Void seektobegin ()
{
Seek (0, cansimemfile: Begin );
}
// Change the file length
// The occupied memory will be re-allocated if needed
Void setlength (DWORD dwnewlen)
{
Assert (this );
If (dwnewlen> m_nbuffersize)
Growfile (dwnewlen );
If (dwnewlen <m_nposition)
M_nposition = dwnewlen;
M_nfilesize = dwnewlen;
Assert (this );
}
// Read data of the specified length from the current read/write location
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;
}
// Write data of the specified length to the file
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 );
}
// Move the read/write location
// Loff moving distance
// Nfrom specifies where to start moving
//
// The second parameter can be:
// 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 error ");
M_nposition = lnewpos;
Assert (this );
Return m_nposition;
}
// Close the memory file and release the occupied memory. Set the length to 0.
// The memory file cannot grow (that is, no data can be written)
// The Destructor automatically calls 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 _)
The following is a simple example of using this class (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", 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", file. getptr ());
Char szdata [] = "123456789 ABCDE ";
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", 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", 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", 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", file. getptr ());
// If this code is added, the following code will fail
// The file cannot be used after it is closed
/* Printf ("***********************/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", 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", 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", file. getptr ());
Printf ("getptr () returns 0x % x. The string is | % S |/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", file. getptr ());
Printf ("seekto 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", 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", file. getptr ());
Return 0;
}