内存映射读取大容量二进制文件



------
请问大家,用内存映射如何读取一个12G大小的二进制文件,我想从文件的第100亿个字节处读取10000个字节,请问大家该如何实现?
------
无需内存映射,用ReadFile加上偏移就行
------
我的读取方式如下:
//获得文件句柄
HANDLE hFile=CreateFile(
"data.dat", //文件名
GENERIC_READ, //对文件进行读操作
FILE_SHARE_READ,
NULL,  
OPEN_EXISTING, //打开已存在文件
FILE_ATTRIBUTE_NORMAL,  
0);  

DWORD size_low,size_high;
size_low= GetFileSize(hFile,&size_high);  

//创建文件的内存映射文件。  
HANDLE hMapFile=CreateFileMapping(  
hFile,  
NULL,  
PAGE_READONLY,  
size_high,  
size_low,  
NULL);  

//把文件数据映射到进程的地址空间
(PBYTE) pvFile = (PBYTE)MapViewOfFile(
hMapFile,  
FILE_MAP_READ,  
0,
0,
0);  


------
MapViewOfFile可以指定偏移量
这个用ReadFile就行了,不要看到大文件就想着CreateFileMapping
------
CreateFileMapping函数设置映射区大小后。
通过MapViewOfFile函数的第三和第四个参数来指定高低偏移量。第5个参数指定要映射的字节数:


------
谢谢二位的回答,可以简单写个例子吗?谢谢了
------
(PBYTE) pvFile = (PBYTE)MapViewOfFile(
hMapFile,  
FILE_MAP_READ,  
0, // 偏移量的高32位
0, // 偏移量的低32位 必须是CPU粒度的整数倍
0); // 视图大小 这里就是10000了 必须是CPU粒度的整数倍

------
DWORD size_low,size_high;
size_low= GetFileSize(hFile,&size_high);  
无法得到12G这么大的值,也就是说我在CreateFileMapping时,无法将该文件全部映射到内存中。
请问Lactoferrin 用ReadFile如何实现从第100亿个字节处读取10000个字节?
------
不共享的话,就用ReadFile吧
------
BOOL WINAPI ReadFile(
  __in HANDLE hFile,
  __out LPVOID lpBuffer,
  __in DWORD nNumberOfBytesToRead,
  __out_opt LPDWORD lpNumberOfBytesRead,
  __inout_opt LPOVERLAPPED lpOverlapped
);
typedef struct _OVERLAPPED {
  ULONG_PTR Internal;
  ULONG_PTR InternalHigh;
  union {
  struct {
  DWORD Offset;
  DWORD OffsetHigh;
  };
  PVOID Pointer;
  };
  HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;

Offset和OffsetHigh就是偏移
------
DWORD size_low,size_high;
size_low= GetFileSize(hFile,&size_high); 

INT64 最大为0xFFFFFFFFFFFFFFFF都多少了??还没有12G大?

size_low= GetFileSize(hFile,&size_high);
得到的是一个64位的值,,高32位在size_high,低32位在size_low.
------
建议使用GetFileSizeEx
------
DWORD无法存放100亿吧?DWORD是unsigned long类型的,在32位下最大是2的32次方-1比100亿小
------
MapViewOfFile的偏移是分成两个参数的,实际上是64位整数
------
0, // 偏移量的高32位
0, // 偏移量的低32位 必须是CPU粒度的整数倍
请问yaojun2偏移量的高32和低32位如何获取?还有 CPU粒度的整数倍是什么意思呢?
------
引用 14 楼 forest2100 的回复:

0, // 偏移量的高32位
0, // 偏移量的低32位 必须是CPU粒度的整数倍
请问yaojun2偏移量的高32和低32位如何获取?还有 CPU粒度的整数倍是什么意思呢?

------
呵呵,大家可以详细举例说明吗?就用我问题中的数值为例,谢谢大家了
------
页的整数倍,就是4096,你可以不提供整数倍的,它会自动改成整数倍
------
请问大家可否给个一楼中的问题中的数据的具体例子?有点模糊,谢谢大家了,内存映射的参数值不知道怎么填写
------
LARGE_INTEGER a;
a.QuadPart=100亿;
dwFileOffsetLow传a.LowPart
dwFileOffsetHigh传a.HighPart
------
HANDLE   hFile=CreateFile(。。。。);

DWORD   dwFileSizeHigh;
__int64   qwFileSize   =   GetFileSize(hFile,   &dwFileSizeHigh);
qwFileSize   |=   (((__int64)dwFileSizeHigh)   < <   32);    
//看这里,qwFileSize是64位,
//dwFileSizeHigh是文件是高32位
//dwFileSizeHigh强制转换成64位后,然后右移32位,与上GetFileSize返回的低32位值,
//就是一个64位表示的文件大小了     难道还不够12G??????

HANDLE   hMap=CreateFileMapping(hFile,PAGE_READ,高32位,低32位,NULL);

PBYTE   pBuf=(PBYTE)MapViewOfFile(
hMap,      
FILE_MAP_READ,      
0x2,                     //偏移量的高32位    
0x540BE400,       //偏移量的低32位         如果是100亿的话,就是0x2540BE400,,那么高位就是0x2,低位就是0x540BE400
10000                   //这里就是粒度的整数,写10000,系统会向上取整。别管粒度是啥了。    
);      


------
谢谢各位的鼎力相助,我在VC6.0下运行了yaojun2提供的代码,运行后,qwFileSize是负数
------
你这样
LARGE_INTEGER size;
GetFileSizeEx(hFile,&size);

------
GetFileSizeEx需要什么头文件?我这不识别这个API
------
我操作系统是XP的
------
windows2000就有了
你头文件过老
------
我也装SP5升级包了,请问我需要在哪更新我的头文件呢
------
安装vc2010
------
《windows核心编程》里面有映射文件一部分到内存的例子。当然,楼主读取指定文件的1000字节,使用ReadFile应该是最方便的办法。
------
能否给个ReadFile的例子说明通过ReadFile如何从指定位置开始读取10000字节的内容?
------
overlapped里面指定
------
Lactoferrin,用ReadFile没有得到值,得到的返回内存信息为空。

刚用 __int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);得到了文件的高位和低位,但是在设置MapViewOfFile时,返回值为空。设置如下:
//创建文件的内存映射文件。  
HANDLE hMapFile=CreateFileMapping(  
hFile,  
NULL,  
PAGE_READONLY,  
size_high,  
size_low,  
NULL);  

//把文件数据映射到进程的地址空间
(PBYTE) pvFile = (PBYTE)MapViewOfFile(
hMapFile,  
FILE_MAP_READ,  
(DWORD)(nOffSet>>32),
(DWORD)(nOffSet & 0xFFFFFFFF),
10000);

  pvFile 为空,请问这是为什么?哪里出错了? 


------
你怎么调用的ReadFile
------
OVERLAPPED tempOverLapp ;
LARGE_INTEGER size ;
size.QuadPart = nOffSet ;
tempOverLapp.Offset = size.LowPart;
tempOverLapp.OffsetHigh = size.HighPart;

char* strByte = new char[nLen+1] ;
memset(strByte,'\0',nLen+1);

unsigned long* nReadLen = new unsigned long;
ReadFile(hFile,strImage,nLen,nReadLen,&tempOverLapp);
------
终于弄出来了,原来低位是需要64K的整数倍,开心啊,哈哈
------
tempOverLapp中的其它成员也要设置好
------
tempOverLapp中的其他成员怎么设置呢?请赐教
------
如果没有特别需求,Pointer 和hEvent要设为0
------
NTSTATUS NtReadFile(
  __in HANDLE FileHandle,
  __in_opt HANDLE Event,
  __in_opt PIO_APC_ROUTINE ApcRoutine,
  __in_opt PVOID ApcContext,
  __out PIO_STATUS_BLOCK IoStatusBlock,
  __out PVOID Buffer,
  __in ULONG Length,
  __in_opt PLARGE_INTEGER ByteOffset,
  __in_opt PULONG Key
);
------
学习。
------
目前属于打酱油的飘过....
桂ICP备07017180号