简体   繁体   English

直接在delphi中访问文件

[英]Direct file access in delphi

my application opens files does transformations and saves the data out to another file..or possible the same file.. the file size changes but i dont know how big or small its gona be untill i see the data inside the first file.. 我的应用程序打开文件进行转换并将数据保存到另一个文件..或可能是同一文件..文件大小发生变化,但是我不知道它的大小,直到我看到第一个文件中的数据。

At the moment i load the file into a dynamic array do all that i need to do in there then save it back... this was looking good untill i got to my testing stage where i found transforming multi gigabyte files on a system with 128mb ram caused some issues...LOL here is my code.. 目前,我将文件加载到动态数组中,然后在其中执行所有操作,然后将其保存回去……这一直很好,直到进入测试阶段,我发现在128MB的系统上转换多千兆字节的文件ram造成了一些问题...这是我的代码..

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;

what i need is direct file access to minimise ram usage.. thats what i think i need/ is this what i need can it be done in delphi 我需要的是直接文件访问以最大程度地减少ram使用..那就是我认为我需要的/这就是我所需要的可以在delphi中完成的事情

I'd look at using a TFileStream, perhaps one with buffering, but you need to show what you are doing with the data really because it is hard to determine the best strategy. 我将研究使用TFileStream,也许是带有缓冲的TFileStream,但是您实际上需要显示对数据的处理方式,因为很难确定最佳策略。 As gabr says, one option is memory mapped files, the code of which is in his link but since it is my code, I'll add it here too! 就像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;

You can also map parts of file directly into memory. 您还可以将文件的一部分直接映射到内存中。 That's definitely the most direct way. 这绝对是最直接的方法。 See What is the fastest way to Parse a line in Delphi for an example. 有关示例,请参见什么是在Delphi中解析线的最快方法

If problem permits, you can use BlockRead and BlockWrite to read chunk of input file, process it and then write that chunk to output file. 如果问题允许,可以使用BlockReadBlockWrite读取输入文件的块,对其进行处理,然后将该块写入输出文件。 Something like this: 像这样:

  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);

Code presumes that you won't change size of buffer while processing it. 代码假定您在处理缓冲区时不会更改其大小。 If size of file changes, then you should change last two lines of example code. 如果文件大小更改,则应更改示例代码的最后两行。

I prefer to use tFileStream for this kind of processing. 我更喜欢使用tFileStream进行这种处理。 In this example I am assuming there is a constant ArraySize which is set to the size of a single array element. 在此示例中,我假设存在一个ArraySize常量,该常量设置为单个数组元素的大小。 For example, if your "array" is an array of integer then it would be set to: 例如,如果您的“数组”是整数数组,则将其设置为:

ArraySize := SizeOf( Integer );

which would set the ArraySize to 4. 这会将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;

The only problem with this approach is it only works for fixed size structures, variable length strings require a different approach. 这种方法的唯一问题是它仅适用于固定大小的结构,可变长度的字符串则需要不同的方法。

I don't think you'll get a "more direct" file access. 我认为您不会获得“更直接”的文件访问权限。 Do you use all the data in the file? 您是否使用文件中的所有数据? Otherwise you could perhaps use a stream and load only the data needed into memory. 否则,您可能会使用流并将仅需要的数据加载到内存中。 But if you use all the data, there's only one solution IMHO: read the file in chunks. 但是,如果使用所有数据,恕我直言只有一种解决方案:分块读取文件。 But that highly depends on the kind of transformation you want to apply. 但这很大程度上取决于您要应用的转换类型。 If the transformation is not local (so that combined data elements are all in the same chunk), you gonna have problems. 如果转换不是局部的(合并的数据元素都在同一块中),那么您将遇到问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 delphi 中的直接 Oracle 访问组件 - working with direct Oracle access components in delphi Delphi HtmlHelpAPI-如何将CHM文件定向到不同的部分 - Delphi HtmlHelpAPI- How to direct a CHM file to open to different sections MySql和Delphi直接连接 - MySql and Delphi direct connection Delphi:拒绝其他进程访问文件 - Delphi: deny access to file for other processes Delphi 10.3 Linux 独占文件访问 - Delphi 10.3 Linux exclusive file access Delphi:文件访问和兼容性文件(Windows 7) - Delphi: File access and compatibility files (windows 7) 使用delphi记录不会在访问文件的末尾插入 - Record not insert in the end of access file with delphi Delphi Direct Oracle Access,DOA 4.0.7.1,TOracleEvent.Stop挂起,如何停止它? - Delphi Direct Oracle Access, DOA 4.0.7.1, TOracleEvent.Stop Hangs, How do I stop it? Delphi重构示例,涉及数据感知控件和可直接访问db表的数据模块 - Example of Delphi refactoring involving data aware controls and datamodules with direct access to db tables 用于 Oracle 云直接模式的 Delphi Devart dbExpress 驱动程序“ORA-03113:通信通道上的文件结束” - Delphi Devart dbExpress driver for Oracle Cloud Direct Mode "ORA-03113:end-of-file on communication channel"
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM