Прямой доступ к файлам в Delphi - PullRequest
1 голос
/ 06 февраля 2009

мое приложение открывает файлы, выполняет преобразования и сохраняет данные в другом файле ... или, возможно, тот же файл ... размер файла изменяется, но я не знаю, насколько большим или маленьким он будет, пока не увижу данные внутри первого файла ..

В тот момент, когда я загружаю файл в динамический массив, делаю все, что мне нужно сделать, и сохраняю его обратно ... это выглядело хорошо, пока я не добрался до стадии тестирования, где обнаружил преобразование мультигигабайтных файлов система с 128 МБ оперативной памяти вызвало некоторые проблемы ... LOL вот мой код ..

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;

мне нужен прямой доступ к файлу, чтобы минимизировать использование оперативной памяти ... вот что мне нужно / это то, что мне нужно, это можно сделать в Delphi

Ответы [ 5 ]

3 голосов
/ 06 февраля 2009

Я бы посмотрел на использование TFileStream, возможно, с буферизацией, но вам нужно показать, что вы действительно делаете с данными, потому что сложно определить лучшую стратегию. Как говорит Габр, один из вариантов - это файлы с отображением в памяти, код которых есть в его ссылке, но, поскольку это мой код, я добавлю его и здесь!

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;
2 голосов
/ 06 февраля 2009

Вы также можете отобразить части файла непосредственно в память. Это определенно самый прямой путь. См. Какой самый быстрый способ разбора строки в Delphi для примера.

1 голос
/ 06 февраля 2009

Я предпочитаю использовать 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;

Единственная проблема этого подхода - он работает только для структур фиксированного размера, строки переменной длины требуют другого подхода.

1 голос
/ 06 февраля 2009

Если проблема разрешается, вы можете использовать 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);

Код предполагает, что вы не будете изменять размер буфера при его обработке. Если размер файла меняется, вам следует изменить последние две строки примера кода.

0 голосов
/ 06 февраля 2009

Не думаю, что вы получите «более прямой» доступ к файлам. Используете ли вы все данные в файле? В противном случае вы можете использовать поток и загружать в память только те данные, которые необходимы. Но если вы используете все данные, ИМХО есть только одно решение: прочитать файл кусками. Но это сильно зависит от того, какую трансформацию вы хотите применить. Если преобразование не является локальным (так что все объединенные элементы данных находятся в одном и том же фрагменте), у вас возникнут проблемы.

...