2008. május 23., péntek

How to read very large text files fast


Problem/Question/Abstract:

Does anyone know the fastest way to read large text files (10Mb) into a string. Readln is just too slow.

Answer:

Solve 1:

You may try this:

function R(const FileName: string): string;
var
  M: TFileStream;
begin
  M := TFileStream.Create(FileName, fmOpenRead);
  try
    SetLength(Result, M.Size);
    M.Read(Result[1], M.Size);
  finally
    M.Free;
  end;
end;


Solve 2:

As an alternative to Christian's suggestion, you can also use a memory-mapped file:

function MMFileToString(const AFilename: string): string;
var
  hFile: THandle;
  hFileMap: THandle;
  hiSize: DWORD;
  loSize: DWORD;
  text: string;
  view: pointer;
begin
  Result := '';
  if AFilename = '' then
    Exit;
  if not FileExists(AFilename) then
    Exit;
  {Open the file}
  hFile := CreateFile(PChar(AFilename), GENERIC_READ, FILE_SHARE_READ, nil,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if hFile <> INVALID_HANDLE_VALUE then
  begin
    loSize := GetFileSize(hFile, @hiSize);
    {File was opened successfully, now map it:}
    hFileMap := CreateFileMapping(hFile, nil, PAGE_READONLY, hiSize,
                 loSize, 'TextForString');
    if (hFileMap <> 0) then
    begin
      if (GetLastError() = ERROR_ALREADY_EXISTS) then
      begin
        MessageDlg('Mapping already exists - not created.', mtWarning, [mbOk], 0);
        CloseHandle(hFileMap)
      end
      else
      begin
        try
          {File mapped successfully, now map a view of the file into
                                        the address space:}
          view := MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
          if (view <> nil) then
          begin {View mapped successfully}
            CloseHandle(hFile);
                                                {Close file handle - as long is view is open it will persist}
            SetLength(Result, loSize);
            Move(view^, Result[1], loSize);
          end
          else
            MessageDlg('Unable to map view of file. ' + SysErrorMessage(GetLastError),
              mtWarning, [mbOk], 0);
        finally
          UnmapViewOfFile(view); {Close view}
          CloseHandle(hFileMap); {Close mapping}
        end
      end
    end
    else
    begin
      MessageDlg('Unable to create file mapping. ' + SysErrorMessage(GetLastError),
        mtWarning, [mbOk], 0);
    end;
  end
  else
  begin
    MessageDlg('Unable to open file. ' + SysErrorMessage(GetLastError),
                 mtWarning, [mbOk], 0);
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése