delphi中的直接文件访问

delphi中的直接文件访问,delphi,file-access,Delphi,File Access,我的应用程序打开文件进行转换并将数据保存到另一个文件..或者可能是同一个文件。。文件大小改变了,但我不知道它的大小,直到我看到第一个文件中的数据 此时,我将文件加载到一个动态数组中,在其中执行所有需要执行的操作,然后将其保存回。。。这看起来不错,直到我进入测试阶段,我发现在一个有128mb内存的系统上转换数十亿字节的文件会导致一些问题…哈哈 这是我的密码 procedure openfile(fname:string); var myfile: file; filesizevalue:i

我的应用程序打开文件进行转换并将数据保存到另一个文件..或者可能是同一个文件。。文件大小改变了,但我不知道它的大小,直到我看到第一个文件中的数据

此时,我将文件加载到一个动态数组中,在其中执行所有需要执行的操作,然后将其保存回。。。这看起来不错,直到我进入测试阶段,我发现在一个有128mb内存的系统上转换数十亿字节的文件会导致一些问题…哈哈 这是我的密码

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进行这种处理