用API打开File Mapping, 为什么在Delphi中不行而VC就可以?(155分)

  • 主题发起人 主题发起人 extrinsic
  • 开始时间 开始时间
E

extrinsic

Unregistered / Unconfirmed
GUEST, unregistred user!
我想在NT4.0下打开1.6G文件的File Mapping, 用Delphi实现如下:
var
FileHandle, MapHandle: Integer;
MemPointer: Pointer;
begin
// Open the file
FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyWrite);
if FileHandle < 0 then
raise EFOpenError.CreateResFmt(@SFOpenError, [FileName]);

// Create file map
try
// Open the file mapping
MapHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);
if MapHandle = 0 then
raise Exception.CreateResFmt(@SFMapError, [FileName]); // 此处出错
finally
FileClose(FileHandle);
end;

// View file map
try
MemPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0); // note: the last but one parameters are not determined
if MemPointer = nil then
raise Exception.CreateResFmt(@SFMapViewError, [FileName]);
finally
CloseHandle(MapHandle);
end;

Result := MemPointer;
end;

但是执行到CreateFileMapping返回得到的总是0, 调用GetLastError返回错误号8,即
内存不够。但是我在同一操作系统下,用VC代码实现就可以正常打开, 如下:

HANDLE hFile, hFileMapping;
LPBYTE pFileData;
DWORD dwIndex, dwSize, dwError;
CString str;

hFile = CreateFile(m_strFile, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);

if (hFile == INVALID_HANDLE_VALUE) {
dwError = GetLastError();
str.Format("Cannot open the file: %d", dwError);
AfxMessageBox(str);
return;
}

// Get File Size
dwSize = GetFileSize(hFile, NULL);

// Open File Mapping for the DLL file
hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hFileMapping == NULL) {
dwError = GetLastError();
str.Format("Cannot map the DLL file: %d", dwError);
AfxMessageBox(str);
return;
}

// Map view of file and get start pointer
pFileData = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
if (pFileData == NULL) {
dwError = GetLastError();
str.Format("Cannot create map view of the file: %d", dwError);
AfxMessageBox(str);
return;
}

二者同是调用API,为什么Dephi不行而 VC可以呢?我用的是Delphi 6.0, VC 6.0 + sp5
 
你不用FileOpen函数,改用CreateFile就可以。
 
这个我以前做过,
for i:=0 to 61 do
begin
TCreatFile:=CreateFile(FilePath,GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
TMapFile:=CreateFileMapping( TCreatFile,nil,Page_ReadWrite,0,
MapFileSize,MapFileName);
PMapFile:=MapViewOfFile(TMapFile,FILE_MAP_READ or FILE_MAP_WRITE,0,0,0);
end;
 
我试过CreateFile的,也不行,调用方式是:

CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

 
补充说明一下,错误是发生在

MemPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);

这一行,调用GetLastError返回错误码8,提示是存储空间不足,无法处理此命令。
 
在delphi中打开vc创建的File map 要精确指定大小(vc 创建时大小必须与delphi打开
时的大小完全一致)
至于原因不太清楚:)(只是也曾经遇到过此问题)。
 
to raindu:
根据API的说明CreateFileMapping和MapViewOfFile中的Size和Offset参数都取0就表明要
将文件的所有内容映射啊.所以我这样应该可以的,而且我的Delphi程序在2000下运行正常,只
有NT4.0下才有此问题.
 
我觉得raindu的说法有道理,用实际的大小,可能是老的API不行把。
 
后退
顶部