//定义了fseek定位大于2G内存映射的文件处理有关的Windows平台的接口
//作者:刘成彬
//适合平台:WindowsXP, WindowsCE
#ifndef _MFILE_H
#define _MFILE_H
#include
typedef unsigned long U32;
class CMFile
{
public:
CMFile();
virtual ~CMFile();
BOOL Open(const char* pszFileName);
BOOL Create(const char* pszFileName, __int64 FileSize);
void Close();
__int64 Read(void* lpBuf, DWORD nLength);
__int64 Write(void* lpBuf, DWORD nLength);
__int64 ReadFile(__int64 nPos, void* lpBuf , DWORD nLength);
__int64 WriteFile(__int64 nPos, void* lpBuf , DWORD nLength);
BOOL SetCursorTo(__int64 nPos);
__int64 GetFileLength();
__int64 GetFilePos();
private:
HANDLE m_hFile; // 文件句柄
HANDLE m_hMapping; // 映射句柄
PBYTE m_pbFile; // 映射内存指针
PBYTE m_pbMapping; // 映射内存指针
__int64 m_nFileSize; // 文件大小
__int64 m_nFilePointer; // 文件当前指针
DWORD m_nSysGranularity; // 系统粒度
BOOL m_bOpened; // 文件打开标志
private:
DWORD MapView(DWORD ViewSize);
};
#endif
===========================================================
#include "MFile.h"
#include
#define MAX_PATH 260
CMFile::CMFile()
{
SYSTEM_INFO si;
GetSystemInfo( &si );
m_nSysGranularity = si.dwAllocationGranularity;
m_hFile = NULL;
m_hMapping = NULL;
m_pbFile = NULL;
m_nFilePointer = NULL;
m_bOpened = FALSE;
m_nFileSize = 0;
}
CMFile::~CMFile()
{
Close();
}
BOOL CMFile::Open(const char* pszFileName)
{
assert(pszFileName);
if(m_bOpened)
Close();
m_hFile = CreateFile(pszFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if(INVALID_HANDLE_VALUE == m_hFile) return FALSE;
DWORD dwFileSizeHigh;
m_nFileSize = GetFileSize(m_hFile, &dwFileSizeHigh);
m_nFileSize += (((__int64) dwFileSizeHigh) << 32);
m_hMapping = CreateFileMapping( m_hFile, NULL, PAGE_READWRITE,(DWORD)(m_nFileSize >> 32), (DWORD)m_nFileSize, NULL );
if (m_hMapping ==NULL)
return FALSE;
m_bOpened = TRUE;
return TRUE;
}
BOOL CMFile::Create(const char* pszFileName, __int64 FileSize)
{
assert(pszFileName);
if(FileSize < 0) return FALSE;
if(m_bOpened)
Close();
m_nFileSize = FileSize;
m_hFile = CreateFile( pszFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
if(INVALID_HANDLE_VALUE == m_hFile) return FALSE;
if(NULL != m_hMapping) UnmapViewOfFile(m_hMapping);
m_hMapping = CreateFileMapping( m_hFile, NULL, PAGE_READWRITE,
(DWORD)(m_nFileSize >> 32), (DWORD)m_nFileSize, NULL );
if(NULL == m_hMapping) return FALSE;
m_bOpened = TRUE;
return TRUE;
}
void CMFile::Close()
{
if(UnmapViewOfFile(m_pbMapping)) m_pbMapping = NULL;
if(CloseHandle(m_hMapping)) m_hMapping = NULL;
if(CloseHandle(m_hFile)) m_hFile = NULL;
m_nFileSize = 0;
m_bOpened = FALSE;
m_pbFile = NULL;
m_nFilePointer = NULL;
m_bOpened = FALSE;
}
__int64 CMFile::Read(void* lpBuf, DWORD nLength)
{
assert(lpBuf);
if(nLength <= 0) return 0;
DWORD MapSize = MapView(nLength);
if(MapSize <= 0) return 0;
memcpy(lpBuf, m_pbFile, MapSize);
SetCursorTo(m_nFilePointer + MapSize);
return MapSize;
}
__int64 CMFile::Write(void* lpBuf, DWORD nLength)
{
assert(lpBuf);
if(nLength <= 0) return 0;
if(m_nFilePointer >= m_nFileSize) return 0;
DWORD MapSize = MapView(nLength);
if(MapSize <= 0) return 0;
memcpy(m_pbFile, lpBuf, MapSize);
SetCursorTo(m_nFilePointer + MapSize);
return MapSize;
}
__int64 CMFile::ReadFile(__int64 nPos, void* lpBuf , DWORD nLength)
{
assert(lpBuf && nLength>0);
if(SetCursorTo( nPos))
return Read(lpBuf , nLength );
else
return 0;
}
__int64 CMFile::WriteFile(__int64 nPos, void* lpBuf , DWORD nLength)
{
assert(lpBuf && nLength>0);
if(SetCursorTo( nPos))
return Write(lpBuf , nLength );
else
return 0;
}
BOOL CMFile::SetCursorTo(__int64 nPos)
{
if(nPos >= m_nFileSize)
{
m_nFilePointer = m_nFileSize;
return FALSE;
}
if(nPos <= 0)
{
m_nFilePointer = 0;
return FALSE;
}
m_nFilePointer = nPos;
return TRUE;
}
__int64 CMFile::GetFileLength()
{
return m_nFileSize;
}
__int64 CMFile::GetFilePos()
{
return m_nFilePointer;
}
/** 函数功能:
根据当前文件指针位置(m_nFilePointer), 和用户要映射的字节数(ViewSize)
将文件映射到内存.同时置m_pbFile的值, 并且返回用户可读写的字节数;
1 根据文件指针位置(m_nFilePointer)计算出最接近系统粒度的整数倍的值
这个值将做为映射的基址
2 映射的字节数, 这个值加上映射基址不能超出文件的总长度
*/
DWORD CMFile::MapView(DWORD ViewSize)
{
assert(m_bOpened);
// 根据当前的文件指针计(m_nFilePointer), 算实际映射位置,
// 这个值必须是系统粒度的整数倍
__int64 nRealPos = (m_nFilePointer / m_nSysGranularity) * m_nSysGranularity;
if(nRealPos >= m_nFileSize) return 0;
// 计算实际应该映射的字节长度
__int64 nRealMapLen = ViewSize + (m_nFilePointer - nRealPos);
if(nRealMapLen > m_nFileSize - nRealPos)
nRealMapLen = m_nFileSize - nRealPos;
// 卸载先前映射
if(NULL != m_pbMapping)
UnmapViewOfFile(m_pbMapping);
// 本次映射
m_pbMapping = (PBYTE)MapViewOfFile( m_hMapping, FILE_MAP_WRITE, (DWORD)(nRealPos >> 32), (DWORD)nRealPos, (DWORD)nRealMapLen);
// 判断
if(NULL == m_pbMapping) return 0;
// 将m_pbFile指针位置置为当前文件指针处
m_pbFile = m_pbMapping + (m_nFilePointer - nRealPos);
// 返回m_pbFile指针的可读写字节数
return (DWORD) (nRealMapLen - (m_nFilePointer - nRealPos));
}