Читать и записывать в двоичный файл? - PullRequest
1 голос
/ 23 декабря 2011

Я сохраняю некоторые пользовательские классы объектов (данные потока) в файл.

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

Это не работает, потому что LoadFromFile не может правильно проанализировать файл. Я предполагаю, что из-за забавных символов Stream сохраняет в файл как, а TStringList ожидает текстовую информацию.

Как мне сделать следующее:

  • Считывание любого двоичного файла в TStringList.
  • Добавить мою новую строку, например StringList1.Add (MyString);
  • Сохраните необработанный двоичный файл снова.

Этот вопрос фактически относится к другому вопросу, который я задал: Сохранить значение CRC в файле, не изменяя фактическую контрольную сумму CRC?

Вот что я пытаюсь сделать:

  • Рассчитать контрольную сумму CRC моего файла сохраненного потока.
  • Добавьте значение CRC в конец файла.
  • Повторно сохранить файл.

Затем, когда я пытаюсь открыть мой потоковый файл:

  • Присвойте значение CRC (в конце файла) переменной.
  • Удалить значение CRC из файла.
  • Сохранить файл потока в качестве нового временного файла.
  • Рассчитать и сравнить CRC временного файла с CRC, хранящимся в переменной.
  • Если CRC файла соответствует внутреннему сохраненному значению CRC, я могу обработать файл как обычно.

Но я не знаю, как читать или записывать необработанные двоичные данные файла.

Буду признателен, если кто-нибудь даст мне помощь и совет, спасибо:)

1 Ответ

5 голосов
/ 23 декабря 2011

Этот класс происходит от TStringList и добавляет проверочное значение в конце при записи в файл. Это значение проверяется всякий раз, когда файл читается.

type
  TCRCStringList = class(TStringList)
  type
    TCRC = LongWord;
  private
    function CalcCRC(Stream: TStream): TCRC;
  public
    procedure LoadFromStream(Stream: TStream; Encoding: TEncoding); override;
    procedure SaveToStream(Stream: TStream; Encoding: TEncoding); override;
  end;

function TCRCStringList.CalcCRC(Stream: TStream): TCRC;
begin
  Result := 42;  // place CRC calculation here
end;

procedure TCRCStringList.LoadFromStream(Stream: TStream; Encoding: TEncoding);
var
  crc: TCRC;
  temp: TMemoryStream;
begin
  temp := TMemoryStream.Create;
  try
    temp.CopyFrom(Stream, Stream.Size - Sizeof(crc));
    Stream.Read(crc, Sizeof(crc));
    if crc <> CalcCRC(temp) then
      raise Exception.Create('CRC error');
    temp.Position := 0;
    inherited LoadFromStream(temp, Encoding);
  finally
    temp.Free;
  end;
end;

procedure TCRCStringList.SaveToStream(Stream: TStream; Encoding: TEncoding);
var
  crc: TCRC;
  temp: TMemoryStream;
begin
  temp := TMemoryStream.Create;
  try
    inherited SaveToStream(temp, Encoding);
    temp.Position := 0;
    crc := CalcCRC(temp);
    temp.Position := temp.Size;
    temp.Write(crc, Sizeof(crc));
    Stream.CopyFrom(temp, 0); // count = 0 copies the whole stream from the beginning
  finally
    temp.Free;
  end;
end;
...