delphi中的直接文件访问
我的应用程序打开文件进行转换并将数据保存到另一个文件..或者可能是同一个文件。。文件大小改变了,但我不知道它的大小,直到我看到第一个文件中的数据 此时,我将文件加载到一个动态数组中,在其中执行所有需要执行的操作,然后将其保存回。。。这看起来不错,直到我进入测试阶段,我发现在一个有128mb内存的系统上转换数十亿字节的文件会导致一些问题…哈哈 这是我的密码delphi中的直接文件访问,delphi,file-access,Delphi,File Access,我的应用程序打开文件进行转换并将数据保存到另一个文件..或者可能是同一个文件。。文件大小改变了,但我不知道它的大小,直到我看到第一个文件中的数据 此时,我将文件加载到一个动态数组中,在其中执行所有需要执行的操作,然后将其保存回。。。这看起来不错,直到我进入测试阶段,我发现在一个有128mb内存的系统上转换数十亿字节的文件会导致一些问题…哈哈 这是我的密码 procedure openfile(fname:string); var myfile: file; filesizevalue:i
procedure openfile(fname:string);
var
myfile: file;
filesizevalue:integer;
begin
AssignFile(myfile,fname);
filesizevalue := GetFileSize(fname);
Reset(myFile, 1);
SetLength(dataarray, filesizevalue);
BlockRead(myFile, dataarray[0], filesizevalue);
CloseFile(myfile);
end;
我需要的是直接访问文件,以最大限度地减少ram的使用。。这就是我想我需要的/
这就是我需要的吗?可以在delphi中完成吗?我认为您不会获得“更直接”的文件访问权限。您是否使用文件中的所有数据?否则,您可能会使用流,只将所需的数据加载到内存中。但是,如果您使用所有数据,IMHO中只有一个解决方案:分块读取文件。但这在很大程度上取决于您想要应用的转换类型。如果转换不是本地的(因此组合的数据元素都在同一块中),您将遇到问题。我认为您不会获得“更直接”的文件访问。您是否使用文件中的所有数据?否则,您可能会使用流,只将所需的数据加载到内存中。但是,如果您使用所有数据,IMHO中只有一个解决方案:分块读取文件。但这在很大程度上取决于您想要应用的转换类型。如果转换不是本地的(因此组合的数据元素都在同一块中),您将遇到问题。您还可以将文件的部分直接映射到内存中。这绝对是最直接的方法。请参阅以获取示例。您还可以将文件的一部分直接映射到内存中。这绝对是最直接的方法。例如,请参阅。我会考虑使用TFileStream,可能是一个带缓冲的,但您需要展示您对数据的实际操作,因为很难确定最佳策略。正如gabr所说,一个选项是内存映射文件,其代码在他的链接中,但由于它是我的代码,我也将它添加到这里
procedure TMyReader.InitialiseMapping(szFilename : string);
var
// nError : DWORD;
bGood : boolean;
begin
bGood := False;
m_hFile := CreateFile(PChar(szFilename), GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0);
if m_hFile <> INVALID_HANDLE_VALUE then
begin
m_hMap := CreateFileMapping(m_hFile, nil, PAGE_READONLY, 0, 0, nil);
if m_hMap <> 0 then
begin
m_pMemory := MapViewOfFile(m_hMap, FILE_MAP_READ, 0, 0, 0);
if m_pMemory <> nil then
begin
htlArray := Pointer(Integer(m_pMemory) + m_dwDataPosition);
bGood := True;
end
else
begin
// nError := GetLastError;
end;
end;
end;
if not bGood then
raise Exception.Create('Unable to map token file into memory');
end;
过程TMyReader.InitialiseMapping(szFilename:string);
变量
//德沃德;
bGood:布尔型;
开始
bGood:=假;
m_hFile:=CreateFile(PChar(szFilename),GENERIC_READ,0,nil,OPEN_EXISTING,0,0);
如果m\u hFile无效\u句柄\u值,则
开始
m_hMap:=CreateFileMapping(m_hFile,nil,PAGE_READONLY,0,0,nil);
如果m_hMap 0那么
开始
m_pMemory:=MapViewOfFile(m_hMap,FILE_MAP_READ,0,0);
如果m_pMemory为零,则
开始
htlArray:=指针(整数(m_pMemory)+m_dwDataPosition);
b好:=真;
终止
其他的
开始
//错误:=GetLastError;
终止
终止
终止
如果不是好的话
引发异常。创建('无法将令牌文件映射到内存');
终止
我会考虑使用TFileStream,可能是一个带缓冲的流,但是您需要展示您对数据的实际操作,因为很难确定最佳策略。正如gabr所说,一个选项是内存映射文件,其代码在他的链接中,但由于它是我的代码,我也将它添加到这里
procedure TMyReader.InitialiseMapping(szFilename : string);
var
// nError : DWORD;
bGood : boolean;
begin
bGood := False;
m_hFile := CreateFile(PChar(szFilename), GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0);
if m_hFile <> INVALID_HANDLE_VALUE then
begin
m_hMap := CreateFileMapping(m_hFile, nil, PAGE_READONLY, 0, 0, nil);
if m_hMap <> 0 then
begin
m_pMemory := MapViewOfFile(m_hMap, FILE_MAP_READ, 0, 0, 0);
if m_pMemory <> nil then
begin
htlArray := Pointer(Integer(m_pMemory) + m_dwDataPosition);
bGood := True;
end
else
begin
// nError := GetLastError;
end;
end;
end;
if not bGood then
raise Exception.Create('Unable to map token file into memory');
end;
过程TMyReader.InitialiseMapping(szFilename:string);
变量
//德沃德;
bGood:布尔型;
开始
bGood:=假;
m_hFile:=CreateFile(PChar(szFilename),GENERIC_READ,0,nil,OPEN_EXISTING,0,0);
如果m\u hFile无效\u句柄\u值,则
开始
m_hMap:=CreateFileMapping(m_hFile,nil,PAGE_READONLY,0,0,nil);
如果m_hMap 0那么
开始
m_pMemory:=MapViewOfFile(m_hMap,FILE_MAP_READ,0,0);
如果m_pMemory为零,则
开始
htlArray:=指针(整数(m_pMemory)+m_dwDataPosition);
b好:=真;
终止
其他的
开始
//错误:=GetLastError;
终止
终止
终止
如果不是好的话
引发异常。创建('无法将令牌文件映射到内存');
终止
如果问题允许,您可以使用BlockRead
和BlockWrite
读取输入文件的块,对其进行处理,然后将该块写入输出文件。大概是这样的:
AssignFile(inFile,inFname);
AssignFile(outFile,outFname);
repeat
BlockRead(inFile, buff, SizeOf(buff), bytesRead);
ProcessBuffer(buff);
BlockWrite(outFile, buff, bytesRead, bytesWritten);
until (bytesRead = 0) or (bytesWritten <> bytesRead);
AssignFile(infle,inFname);
AssignFile(outFile,outname);
重复
块读(填充、浅黄色、大小(浅黄色)、字节读);
进程缓冲区(buff);
块写入(输出文件、buff、字节读取、字节写入);
直到(字节读=0)或(字节读写字节读);
代码假定在处理缓冲区时不会更改缓冲区的大小。如果文件大小发生变化,则应更改示例代码的最后两行。如果问题允许,您可以使用
块读
和块写
读取输入文件的块,对其进行处理,然后将该块写入输出文件。大概是这样的:
AssignFile(inFile,inFname);
AssignFile(outFile,outFname);
repeat
BlockRead(inFile, buff, SizeOf(buff), bytesRead);
ProcessBuffer(buff);
BlockWrite(outFile, buff, bytesRead, bytesWritten);
until (bytesRead = 0) or (bytesWritten <> bytesRead);
AssignFile(infle,inFname);
AssignFile(outFile,outname);
重复
块读(填充、浅黄色、大小(浅黄色)、字节读);
进程缓冲区(buff);
块写入(输出文件、buff、字节读取、字节写入);
直到(字节读=0)或(字节读写字节读);
代码假定在处理缓冲区时不会更改缓冲区的大小。如果文件大小发生变化,则应更改示例代码的最后两行。我更喜欢使用tFileStream进行此类处理。在本例中,我假设存在一个常数ArraySize,该常数设置为单个数组元素的大小。例如,如果“数组”是一个整数数组,则它将设置为:
ArraySize := SizeOf( Integer );
这会将ArraySize设置为4
Function LoadPos(inFIlename:string;ArrayPos:Int64;var ArrayBuff) : boolean;
var
fs : tFileStream;
begin
result := false;
fs := tFileStream.Create(inFilename,fmOpenRead);
try
// seek to the array position
fs.Seek( ArrayPos * ArraySize, soFromBeginning);
// load the element
result := fs.Read( ArrayBuff, ArraySize ) = ArraySize;
finally
fs.free;
end;
end;
这种方法的唯一问题是它只适用于固定大小的结构,可变长度的字符串需要不同的方法。我更喜欢使用tFileStream进行这种处理