procedure TForm1.UpdateFile(Input: pointer; Length: Integer);
var
p:PByte;
I:Integer;
begin
p:= PByte(Input);
for i := 0 to Length - 1 do
begin
//处理p^的数据;这也是要保存的数据
inc(p);
end;
end;procedure TForm1.Button1Click(Sender: TObject);
var
FileHandle: THandle;
MapHandle: THandle;
ViewPointer: pointer;
N:String;
begin
n:=Edit1.text;
FileHandle := CreateFile(PChar(N), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
if FileHandle <> INVALID_HANDLE_VALUE then try
MapHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);
if MapHandle <> 0 then try
ViewPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
//如何映像大文件,>于4G、10G等???
if ViewPointer <> nil then
begin
try
UpdateFile(ViewPointer, GetFileSize(FileHandle, nil));
//UpdateFile(ViewPointer, 1024*30000);
finally
UnmapViewOfFile(ViewPointer);
end;
end;
finally
CloseHandle(MapHandle);
end;
finally
CloseHandle(FileHandle);
end;
end;
如何映像大文件,>于4G、10G等???
我想文件在UpdateFile里对数据进行处理后,怎样将数据保存为文件?
解决方案 »
- 奇怪了 帮忙看看Image1的问题
- 程序员偶得闲技术区,欢迎大家加入我的技术群,共同讨论程序中的心得和体会
- Delphi7和Delphi2006中的IdUDPServer1UDPRead不一样了,该怎么办?
- 求一ActiveX控件,从机器的90端口读数据。
- 初来这里,帮别人问个问题...麻烦一下
- 朋友!!请帮帮忙!!困惑我一个的问题!!c/s 的实现
- 这个用delphi写的函数是什么意思
- 用程序让机器重起。怎么实现(delphi)?
- 有没有人写过,把REG文件导入注册表的程序?不要调用regedit.exe啊
- 为什么reset()函数无法读取只读文件,有没有解决的办法?
- 进程外自动化服务器能做成windows服务么?
- 公司打算采购一套IVR系统,做这的朋友请联系
hFile:THandle;
lpFileMappingAttributes:PSecurityAttributes;
flProtect:DWORD;
dwMaximumSizeHigh:DWORD;
dwMaximumSizeLow:DWORD;
lpName:PChar
):THandle;
当文件大于4GB时,参数dwMaximumSizeHigh用于指定文件映像的高32位,dwMaximumSizeLow指定低32位
var
pName: PChar;
begin
if FFileHandle = 0 then exit; //文件句柄为空,退出; //创建映射文件;
if IsShareMem then
begin
pName := PChar(FMappingName);
FMapHandle := CreateFileMapping(FFileHandle, nil, GetFileMappingMode,
Int64Rec(FMapFileTotalSize).Hi, Int64Rec(FMapFileTotalSize).Lo, pName);
if (FMapHandle <> 0) and (GetLastError = ERROR_ALREADY_EXISTS) then
begin
CloseHandle(FMapHandle);
FMapHandle := 0;
FMapHandle := OpenFileMapping(GetFileMapViewMode, False, pName);
end;
end
else
FMapHandle := CreateFileMapping(FFileHandle, nil, GetFileMappingMode,
Int64Rec(FMapFileTotalSize).Hi, Int64Rec(FMapFileTotalSize).Lo, nil); ViewPage;
end;procedure TMappingFileStream.ViewPage;
begin
if FMapHandle = 0 then exit;
FPageStartPos := MapViewOfFile(FMapHandle, GetFileMapViewMode,
Int64Rec(FPageStartOffset).Hi, Int64Rec(FPageStartOffset).Lo, FPageFactSize);
FPageCurrPos := FPageStartPos;
if FFileHeaderEnabled then
FFileHeader := MapViewOfFile(FMapHandle, GetFileMapViewMode, 0, 0, FFileHeaderSize);
end;剩下的逻辑你自己封装吧,道理是先映射文件的一部分,然后独到后面在映射剩下的一部分。
我的博客里,留下了内存映射的研习代码。
现在打不开,没办法给你具体的网址。
有机会可以去看看。
我得到的结论是,内存映射和TMemoryStream 差不多效率。
This function creates a named or unnamed file-mapping object for the specified file. HANDLE CreateFileMapping(
//通过调用fileopen or FileCreate后返回的文件句柄,如果是内存,则//$FFFFFFFF
HANDLE hFile,
//安全性结构,一般null
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
//文件试图的保护类型,PAGE_READONLY,PAGE_READWRITE,
DWORD flProtect,
//文件大小的高32位,一般设置为0,除非文件大于4G
DWORD dwMaximumSizeHigh,
//文件大小低32位
DWORD dwMaximumSizeLow,
//映射的名字
LPCTSTR lpName
); 2、打开一个映射文件
HANDLE OpenFileMapping(
//访问数据模式:FILE_MAP_ALL_ACCESS,FILE_MAP_COPY,FILE_MAP_READ, //FILE_MAP_WRITE
DWORD dwDesiredAccess,
//子进程是否可以继承
BOOL bInheritHandle,
//映射文件名
LPCTSTR lpName
);
3、将映射文件映射到本进程的API函数
LPVOID MapViewOfFile(
//通过CreateFileMapping或OpenFileMapping返回的文件句柄
HANDLE hFileMappingObject,
//访问的数据模式:FILE_MAP_WRITE,FILE_MAP_READ,FILE_MAP_ALL_ACCESS
DWORD dwDesiredAccess,
//指定数据在映射文件中起始位置的高32位
DWORD dwFileOffsetHigh,
//低32位
DWORD dwFileOffsetLow,
//需要映射的大小,0表示全部
DWORD dwNumberOfBytesToMap
);
4、关闭映射的api函数
BOOL UnmapViewOfFile(
//由MapViewofFile产生的映射文件的地址
LPCVOID lpBaseAddress
);
5、下面例子中还会用到的几个api函数 创建互斥对象
HANDLE WINAPI CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
); DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
library Project1;
uses
shareMem,
windows,
SysUtils,
Classes;
const
MFileName: Pchar = ’ShareData’;
//定义一个记录类型,你所需要共享的数据就保存在这里。
//当在进程中调用GetDllData时,进程中也应该定义一个与这个一样的记录类型。
type
PGlobalDllData = ^TGlobalDllData;
TGlobalDllData = record
s: string[50];
i: integer;
end;var
GlobalData: PGlobalDllData; //这是一个全局变量,指向创建的内存映射文件。
MapHandle: THandle;
//给外部进程调用的过程,当外部进程调用这个过程后,形参AGlobalData就指向了我//们创建的内存映射文件. 我们可以创建两个进程, 同时调用这个过程, 那么在其中一个进 //程中修改数据后, 在另外一个进程中既可反应出来, 实现了我们需要的共享.procedure GetDllData(var AGlobalData: PGlobalDllData);stdcall; begin
AGlobalData := GlobalData;
end;procedure OpenThisData;
var
size: integer;
begin
size := sizeof(TGlobalDllData);
//创建一个内存文件映射对象,MfileName保存的值就是该对象的名字。
mapHandle := CreateFileMapping(Dword(-1), nil, page_readWrite, 0, size, MFileName); if mapHandle = 0 then
RaiseLastWin32Error;
//把文件的视图映射到调用进程的地址空间,该函数的返回值就是该对象的首地址。注//意,这是调用进程的地址,两个应用程序调用该DLL,返回值是不一样的。
GlobalData := MapViewOfFile(mapHandle, File_map_all_Access, 0, 0, size); Globaldata^.s := ’TEST’;
GlobalData^.i := 5;
if GlobalData = nil then
begin
CloseHandle(MapHandle);
RaiseLastWin32Error;
end;
end;
//DLL从进程中分离出来时,应该释放相应的空间
procedure CloseThisData;
begin
unmapViewOfFile(GlobalData);
closeHandle(MapHandle);
end;procedure DllEntryPoint(dwReason: DWord);
begin
case dwReason of
Dll_Process_Attach: OpenThisData; //调用DLL时传入的参数,由系统自动传入
Dll_Process_Detach: CloseThisData; //释放DLL时传入的参数,系统自动传入。
end;
end;{$R *.res}exports
GetDllData; //外部应用程序调用的就是这个过程。
begin
DllProc := @DllEntryPoint; //该变量是一个全局变量,由它来指定DLL的入口及出 //口函数。
DllEntryPoint(Dll_Process_Attach);
end.