Re: How to create a file in RAM ?
kathy ha scritto:
On Aug 7, 9:10 am, kathy <yqin...@yahoo.com> wrote:
Read / Write to disk file is too slow. How to create a file in RAM
memory so that I could read / write to memory?
by the way, I would like to read line by line. My file is text file.
In addition to what we already wrote, you may want to use memory mapped
techniques to access file for reading.
You can find a complete MFC simple application (with source code) that
reads a text file using memory mapping and parses file lines here:
http://www.geocities.com/giovanni.dicanio/vc/TestFileInMemory.zip
The class that implements the simple memory mapping technique for file
reading is CMemoryMappedTextFile; instead you can find the line parsing
algorithm in CTestReadFileDlg::OnBnClickedReadFile() method.
The content of the file is assumed to be plain ASCII (no Unicode).
In case you have e.g. a UTF-8 text file, you can simply convert the read
lines to Unicode UTF-16 using ::MultiByteToWideChar Win32 API.
Here is part of the code that uses the read-only memory-mapped text file
class to parse file content line by line.
(This code is from CTestReadFileDlg::OnBnClickedReadFile() method.)
<code>
...
// Clear displayed file content
m_lstFileContent.ResetContent();
// Open file for reading
CMemoryMappedTextFile file(filename);
if (! file.IsReady())
{
AfxMessageBox(IDS_ERROR_FILE_OPEN, MB_OK|MB_ICONERROR);
return;
}
//
// Parse file lines from memory mapped file.
// Assume that the file stores pure ASCII data.
//
// Points to the beginning of file.
// This pointer will be moved forward during file scanning.
const char * pchFileContent = file.GetBuffer();
ASSERT(pchFileContent != NULL);
// Pointer to end of file
const char * pchEnd = pchFileContent + file.GetLength();
// Parse file content, adding each line to the listbox
while (pchFileContent < pchEnd)
{
// Find line terminator ('\n')
const char * pchEndOfLine = std::find(pchFileContent, pchEnd,
'\n');
// Get length of line in characters
int lineLength = pchEndOfLine - pchFileContent - 1;
// Store a copy of current line using CStringA instance
// (text is not Unicode)
CStringA line(pchFileContent, lineLength );
// Move scanning pointer to next line
pchFileContent = pchEndOfLine + 1;
// Add string to listbox
m_lstFileContent.AddString( CA2T(line) );
}
// CMemoryMappedTextFile destructor does proper cleanup.
// (Thanks RAII)
</code>
The implementation of CMemoryMappedTextFile class follows:
--------------------------------------------------------------------------
--------------------------------------------------------------------------
<file name="MemoryMappedTextFile.h">
//////////////////////////////////////////////////////////////////////////
// FILE: MemoryMappedTextFile.h
//////////////////////////////////////////////////////////////////////////
#pragma once
//========================================================================
// Manages a read-only memory-mapped file
// (maximum 4 GB in size).
//========================================================================
class CMemoryMappedTextFile
{
public:
// Initializes the object to read the specified file
CMemoryMappedTextFile(LPCTSTR filename);
// Cleanup
~CMemoryMappedTextFile();
// Pointer to file content
// (if object initialization failed, NULL is returned)
const char * GetBuffer() const;
// Returns file size, in bytes
DWORD GetLength() const;
// Was file mapping created successfully?
BOOL IsReady() const;
//
// IMPLEMENTATION
//
private:
HANDLE m_hFile; // File handle
HANDLE m_hFileMapping; // File mapping handle
char * m_pContent; // Pointer to file content
DWORD m_cbSize; // File size, in bytes
};
//------------------------------------------------------------------------
// INLINE METHOD IMPLEMENTATIONS
//------------------------------------------------------------------------
inline const char * CMemoryMappedTextFile::GetBuffer() const
{
return m_pContent;
}
inline DWORD CMemoryMappedTextFile::GetLength() const
{
return m_cbSize;
}
inline BOOL CMemoryMappedTextFile::IsReady() const
{
return ( m_pContent != NULL ? TRUE : FALSE );
}
</file>
--------------------------------------------------------------------------
--------------------------------------------------------------------------
<file name="MemoryMappedTextFile.cpp">
//////////////////////////////////////////////////////////////////////////
// FILE: MemoryMappedTextFile.cpp
//////////////////////////////////////////////////////////////////////////
#include "stdafx.h" // Precompiled header
#include "MemoryMappedTextFile.h" // Class header
//------------------------------------------------------------------------
// METHOD IMPLEMENTATIONS
//------------------------------------------------------------------------
CMemoryMappedTextFile::CMemoryMappedTextFile(LPCTSTR filename)
: m_hFile(INVALID_HANDLE_VALUE), m_hFileMapping(NULL), m_pContent(NULL),
m_cbSize(0)
{
ASSERT(filename != NULL);
// Open file for reading
m_hFile = CreateFile(
filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (m_hFile == INVALID_HANDLE_VALUE)
return;
// Get file size
DWORD cbSize = GetFileSize(m_hFile, NULL);
// Create file mapping (read-only)
m_hFileMapping = CreateFileMapping(
m_hFile,
NULL,
PAGE_READONLY,
0,
0,
NULL
);
if (m_hFileMapping == NULL)
return;
// Get pointer to file content
m_pContent = reinterpret_cast<PCHAR>(
MapViewOfFile(m_hFileMapping, FILE_MAP_READ, 0, 0, cbSize)
);
if (m_pContent == NULL)
return;
// Store size field
m_cbSize = cbSize;
}
CMemoryMappedTextFile::~CMemoryMappedTextFile()
{
//
// Safely cleanup everything
//
if (m_pContent)
{
UnmapViewOfFile(m_pContent);
m_pContent = NULL;
}
if (m_hFileMapping)
{
CloseHandle(m_hFileMapping);
m_hFileMapping = NULL;
}
if (m_hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
}
</file>
--------------------------------------------------------------------------
--------------------------------------------------------------------------
HTH,
Giovanni