内存映射文件问题

zxfishhack 上海汇纳 高级开发工程师  2009-08-14 09:11:48
完整源代码:(关键代码在后面有整理。查找“关键代码”即可)
#include <windows.h>
#include <iostream>
#include <iomanip>
#include <time.h>
using namespace std;

const __int64 FLUSH_SIZE = 0x8000000;

#define FILEIN xxxx
#define FILEOUT xxxx
int main()
{
char * _buff;
clock_t s,e;
char t;
float percent=0,bpercent=0;
HANDLE hFileIn = CreateFile(FILEIN,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS,
NULL);
HANDLE hFileOut = CreateFile(FILEOUT,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
DWORD dwFileSizeHigh;
if (hFileIn == INVALID_HANDLE_VALUE)
{
cout<<"Open File "<<FILEIN<<" Error. Error Code "<<GetLastError()<<endl;
return -1;
}
if (hFileOut == INVALID_HANDLE_VALUE)
{
cout<<"Open File "<<FILEOUT<<" Error. Error Code "<<GetLastError()<<endl;
return -1;
}
__int64 qwFileSize = GetFileSize(hFileIn, &dwFileSizeHigh);
qwFileSize |= (((__int64)dwFileSizeHigh) << 32);

cout<<setprecision(2)<<fixed;
cout<<"The file size is:"<<qwFileSize / 1024.0 / 1024.0<<"MB"<<endl;

HANDLE hFileInMapping = CreateFileMapping(hFileIn,NULL,PAGE_READONLY, 0, 0, NULL);
if(hFileInMapping == NULL)
{
cout<<"Mapping File for input failed. Error Code "<<GetLastError()<<endl;
CloseHandle(hFileIn);
CloseHandle(hFileOut);
return -1;
}
HANDLE hFileOutMapping = CreateFileMapping(hFileOut,NULL,PAGE_READWRITE,qwFileSize >> 32, qwFileSize & 0xFFFFFFFF, NULL);
if(hFileOutMapping == NULL)
{
cout<<"Mapping File for output failed. Error Code "<<GetLastError()<<endl;
CloseHandle(hFileInMapping);
CloseHandle(hFileIn);
CloseHandle(hFileOut);
return -1;
}
CloseHandle(hFileIn);
CloseHandle(hFileOut);


SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);

// 设定大小、偏移量等参数
DWORD dwGran = SysInfo.dwAllocationGranularity;
__int64 qwFileOffset = 0;
__int64 ByteBuffing = 0;
static int REMAP = 90;
static int TOTALMAP = 100;
static int GRAN_PER_BLOCK = 10;
__int64 T_newmap = REMAP * dwGran;
DWORD dwBlockBytes = TOTALMAP * dwGran;


_buff = new char[GRAN_PER_BLOCK * dwGran];
if (qwFileSize - qwFileOffset < dwBlockBytes)
dwBlockBytes = (DWORD)qwFileSize;
char * pbFile = (char *)MapViewOfFile(hFileInMapping,FILE_MAP_READ,(DWORD)(qwFileOffset>>32),
(DWORD)(qwFileOffset&0xFFFFFFFF), dwBlockBytes);
if(pbFile == NULL)
{
cout<<"Mapping File view for input failed."<<endl;
CloseHandle(hFileInMapping);
CloseHandle(hFileOutMapping);
return -1;
}
char * pbFile2 = (char *)MapViewOfFile(hFileOutMapping,FILE_MAP_WRITE,(DWORD)(qwFileOffset>>32),
(DWORD)(qwFileOffset&0xFFFFFFFF), dwBlockBytes);
if(pbFile2 == NULL)
{
cout<<"Mapping File view for output failed."<<endl;
UnmapViewOfFile(pbFile);
CloseHandle(hFileInMapping);
CloseHandle(hFileOutMapping);
return -1;
}
DWORD offset = 0;
s = clock();
while(qwFileOffset < qwFileSize)
{
percent = float(qwFileOffset);
if(percent > qwFileSize) percent = 100;
else percent = percent / qwFileSize * 100;
if( percent - bpercent > 0.05){
bpercent = percent;
e = clock();
cout<<(double)(e - s) / CLOCKS_PER_SEC<<"s elapsed."<<qwFileOffset / 1024.0 / 1024.0<<"MB Copyed,"<<setw(6)<<percent<<"% completed.\r";
}

if (qwFileOffset > T_newmap)
{
UnmapViewOfFile(pbFile);
FlushViewOfFile(pbFile2,0);
UnmapViewOfFile(pbFile2);
if ((DWORD)(qwFileSize - T_newmap) < dwBlockBytes)
{
dwBlockBytes = (DWORD)(qwFileSize - T_newmap);
}
pbFile = (char *)MapViewOfFile(hFileInMapping,FILE_MAP_READ,
(DWORD)(T_newmap >> 32), (DWORD)(T_newmap & 0xFFFFFFFF),dwBlockBytes);
if(pbFile == NULL)
{
cout<<"Mapping File view for input failed."<<endl;
CloseHandle(hFileInMapping);
CloseHandle(hFileOutMapping);
return -1;
}
pbFile2 = (char *)MapViewOfFile(hFileOutMapping,FILE_MAP_WRITE,
(DWORD)(T_newmap >> 32),(DWORD)(T_newmap & 0xFFFFFFFF),dwBlockBytes);
if(pbFile2 == NULL)
{
cout<<"Mapping File view for output failed."<<endl;
UnmapViewOfFile(pbFile);
CloseHandle(hFileInMapping);
CloseHandle(hFileOutMapping);
CloseHandle(hFileIn);
CloseHandle(hFileOut);
return -1;
}
// 修正参数
offset = qwFileOffset - T_newmap;
T_newmap =T_newmap + REMAP * dwGran;
}
if(qwFileSize - qwFileOffset > GRAN_PER_BLOCK * dwGran)//有足够的数据读出
{
memcpy(pbFile2 + offset, pbFile + offset,GRAN_PER_BLOCK * dwGran);
offset += GRAN_PER_BLOCK * dwGran;
qwFileOffset += GRAN_PER_BLOCK * dwGran;
ByteBuffing += GRAN_PER_BLOCK * dwGran;
}
else
{
memcpy(pbFile2 + offset,pbFile + offset,int(qwFileSize - qwFileOffset));
qwFileOffset += qwFileSize - qwFileOffset;
}
}
e = clock();
UnmapViewOfFile(pbFile);
UnmapViewOfFile(pbFile2);
CloseHandle(hFileInMapping);
CloseHandle(hFileOutMapping);
cout<<qwFileOffset / 1024.0<<"KB Readed,100.00% completed."<<endl;
cout<< (double)(e - s) / CLOCKS_PER_SEC<<"s elapsed."<<endl;
cin>>t;
return 0;
}

“关键代码”:

const __int64 FLUSH_SIZE = 0x8000000;

HANDLE hFileIn = CreateFile(FILEIN,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS,
NULL);
HANDLE hFileOut = CreateFile(FILEOUT,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);

__int64 qwFileSize = GetFileSize(hFileIn, &dwFileSizeHigh);
qwFileSize |= (((__int64)dwFileSizeHigh) << 32);

HANDLE hFileInMapping = CreateFileMapping(hFileIn,NULL,PAGE_READONLY, 0, 0, NULL);
HANDLE hFileOutMapping = CreateFileMapping(hFileOut,NULL,PAGE_READWRITE,qwFileSize >> 32, qwFileSize & 0xFFFFFFFF, NULL);

// 设定大小、偏移量等参数
DWORD dwGran = SysInfo.dwAllocationGranularity;
__int64 qwFileOffset = 0;
__int64 ByteBuffing = 0;
static int REMAP = 90;
static int TOTALMAP = 100;
static int GRAN_PER_BLOCK = 10;
__int64 T_newmap = REMAP * dwGran;
DWORD dwBlockBytes = TOTALMAP * dwGran;

首次建立View:
char * pbFile = (char *)MapViewOfFile(hFileInMapping,FILE_MAP_READ,(DWORD)(qwFileOffset>>32),
(DWORD)(qwFileOffset&0xFFFFFFFF), dwBlockBytes);
char * pbFile2 = (char *)MapViewOfFile(hFileOutMapping,FILE_MAP_WRITE,(DWORD)(qwFileOffset>>32),
(DWORD)(qwFileOffset&0xFFFFFFFF), dwBlockBytes);

重新建立View:
if (qwFileOffset > T_newmap)
{
UnmapViewOfFile(pbFile);
FlushViewOfFile(pbFile2,0);
UnmapViewOfFile(pbFile2);
if ((DWORD)(qwFileSize - T_newmap) < dwBlockBytes)
{
dwBlockBytes = (DWORD)(qwFileSize - T_newmap);
}
pbFile = (char *)MapViewOfFile(hFileInMapping,FILE_MAP_READ,
(DWORD)(T_newmap >> 32), (DWORD)(T_newmap & 0xFFFFFFFF),dwBlockBytes);
pbFile2 = (char *)MapViewOfFile(hFileOutMapping,FILE_MAP_WRITE,
(DWORD)(T_newmap >> 32),(DWORD)(T_newmap & 0xFFFFFFFF),dwBlockBytes);
// 修正参数
offset = qwFileOffset - T_newmap;
T_newmap =T_newmap + REMAP * dwGran;
}
此程序在处理4G以下文件时能正常实现复制功能,而在处理超过4G的文件时(记文件大小为4G * n + m),在映射m大小之后出错。完整源代码在最前。
...全文
80 点赞 收藏 3
写回复
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
zxfishhack 2012-05-31
if ((DWORD)(qwFileSize - T_newmap) < dwBlockBytes) //此句有问题,直接导致32位截断。
{
dwBlockBytes = (DWORD)(qwFileSize - T_newmap);
}

回复
evileagle 2009-08-28
32位系统吧?32位系统内存寻址最大4G
回复
Bbbbbbone 2009-08-14
LZ代码有问题
接分.
回复
发动态
发帖子
硬件/系统
创建于2007-09-28

2589

社区成员

VC/MFC 硬件/系统
申请成为版主
社区公告
暂无公告