如题,请高手赐教。谢谢!!!
GetMem(q,43800000);你没检查q的内存是否申请成功了,没申请成功,你后面的操作都是无效的,因为你所要的内存比较大,有时不见得能成功申请到
申请成功且文件又成功读到你分配的内存后,下面一句也可能会有问题的
Memo1.Lines.Add(Format('文件:%s',[BytesToString(@q)]));
60多M的数据,你转成可见字符,一般可能是hex格式,容量至少加一倍,那就是近120M,默认的memo能显示得了?你可以用用xp的记事本打开50m的文件看看,能打开不
我猜想你大致想把文件内容在memo中展示出来,不过这个思路即便能成功,可是你使用起来很费时,加载及显示都比较慢,而且内存分配也有问题,没有特殊必要不会太夸张的进行内存申请;
用filestream其实也可以,你也不用申请那么大的内存,你界面上能看到的可能也就几行,你可以做个游标,要看哪一部分时,把stream.pos移动一下,只转换很小的一部分显示出来即可,这样速度也快,编程起来也不麻烦
基本功能实现了调优的话可以用内存映射,winhex就是内存映射整的
7楼补充了我遗漏的创建文件句柄
核心还是内存映射
我给出的有何不对之处?
我用$FFFFFFFF做了文件句柄,这里如何得到文件句柄,我想愿意学的话很容易找到方法吧
六楼的不对,你那个是内存共享映射,不是文件读取,不过代码也差不多类似,我粗略做了个函数,建议封成类,使用更灵活,64M 用TFileStream其实也可以,可能没内存映射快。
解决方案4:
function FastReadFile(FileName: string): Integer;
const
PAGE_SIZE = 4 * 1024; //映射块大小不易过大,尽量以4k对齐
var
hFile: THandle;
szHigh,szLow: DWORD;
szFile,ps: Int64;
hMap: THandle;
hData: Pointer;
dwSize: Cardinal;
begin
Result := -1;
hFile := 0;
hMap := 0;
hData := nil;
szHigh := 0;
try
//打开已存在的文件,获得文件句柄
hFile := CreateFile(PChar(FileName),GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,
nil,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
if hFile = 0 then
begin
Result := GetLastError;
Exit;
end;
//获取文件大小
hMap := 0;
hData := nil;
szHigh := 0;
szLow := GetFileSize(hFile,@szHigh);
szFile := szLow or (szHigh shl 32);
//创建映射句柄
hMap := CreateFileMapping(hFile, nil, PAGE_READWRITE, szHigh, szLow, nil);
if hMap = 0 then
begin
Result := GetLastError;
Exit;
end;
ps := 0;
//文件可能比较大,分块进行映射
while ps < szFile do
begin
//计算映射大小及位置
if szFile - ps > PAGE_SIZE then
dwSize := PAGE_SIZE
else
dwSize := szFile - ps;
szLow := ps and $FFFFFFFF;
szHigh := ps shr 32;
//进行映射
hData := MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,szHigh,szLow,dwSize);
if hData = nil then
Break;
try
//此时文件偏移ps处的数据通过hData即可读取到,块大小为dwSize
//以下加上你读取的代码,可以做一个回调函数
//比如你要当前位置的数据(取文件数)拷到指定内存处 CopyMemory(目标地址指针,hData,dwSize);
//
finally
//移动文件偏移位置
ps := ps + dwSize;
//释放映射块
UnmapViewOfFile(hData);
hData := nil;
end;
end;
finally
//释放必要资源
if hData <> nil then
UnmapViewOfFile(hData);
if hMap <> 0 then
CloseHandle(hMap);
if hFile <> 0 then
CloseHandle(hFile);
end;
end;
PShareMem = ^TShareMem;
TShareMem = Record
id:string[10];
name:string[20];
age:Integer;
end;
shareMemName:string; //共享内存名
fileHandle : THandle;//内存映射文件句柄
pUserInfoShareMem : PShareMem;//指向共享内存的指针
begin
//创建“内存映射文件”
fileHandle:=CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TShareMem), PChar(shareMemName));
if fileHandle <> 0 then
begin
Self.Memo1.Lines.Add('已成功创建内存映射文件!');
end;
end;
//将“内存映射文件”与“应用程序地址空间”建立映射关系
pUserInfoShareMem:=MapViewOfFile(fileHandle,FILE_MAP_ALL_ACCESS,0,0,sizeof(TShareMem));
if pUserInfoShareMem <> nil then
begin
Self.Memo1.Lines.Add('已成功建立映射关系!');
end;
pUserInfoShareMem.id:='8888';
pUserInfoShareMem.name:='Terry';
pUserInfoShareMem.age:=25;
Self.Memo1.Lines.Add('已向共享内存中写入用户信息!');
//解除“内存映射文件”与“应用程序地址空间”的映射关系
if pUserInfoShareMem<> nil then
UnmapViewOfFile(pUserInfoShareMem);
Self.Memo1.Lines.Add('已成功解除映射关系!');
//关闭内存映射文件
if fileHandle<> 0 then
CloseHandle(fileHandle);
Self.Memo1.Lines.Add('已成功关闭内存映射文件!');