【问题标题】:Read and Write to Binary File?读写二进制文件?
【发布时间】:2012-01-26 21:55:53
【问题描述】:

我正在将一些自定义创建的对象类(流数据)保存到文件中。

我需要能够将文件的内容加载到 TStringList 中,这样我就可以在文件末尾追加一个新行,然后保存更改。

这不起作用,因为 LoadFromFile 似乎无法正确解析文件。我假设由于流保存到文件的有趣字符,并且 TStringList 需要纯文本信息。

我怎样才能做到以下几点:

  • 将任何原始二进制文件读入 TStringList。
  • 添加我的新行,例如 StringList1.Add(MyString);
  • 再次保存原始二进制文件。

这个问题实际上与我问的另一个问题有关:Save a CRC value in a file, without altering the actual CRC Checksum?

这就是我想要做的:

  • 计算我保存的流文件的 CRC 校验和。
  • 将 CRC 值添加到文件末尾。
  • 重新保存文件。

然后当我尝试打开我的流文件时:

  • 将 CRC 值(位于文件末尾)分配给变量。
  • 从文件中删除 CRC 值。
  • 将流文件另存为新的临时文件。
  • 计算并比较临时文件的 CRC,与存储在变量中的 CRC。
  • 如果文件的 CRC 与内部存储的 CRC 值匹配,我可以正常处理文件。

但我不知道如何读取或写入文件的原始二进制数据。

如果有人能给我一些帮助和建议,我将不胜感激:)

【问题讨论】:

  • 您正在将校验和保存到文本文件中?那是对的吗?我还是不明白你为什么需要校验和。
  • 保存到流文件,我这样做是为了每当从我的应用程序中打开一个文件时,我都可以确定该文件是否实际上是从我的程序中保存的。
  • 您使用的是什么版本的Delphi?它对 Unicode 字符串(或不)特别重要
  • 检测到损坏的文件并报告错误会好得多。如果用户弄乱了文件,那就是他们的问题。将其存储在他们的用户个人资料下,他们没有理由乱用它。
  • 克雷格;免费小费;二进制文件很麻烦。如果您不需要制作自定义二进制文件格式,那就不要。文本文件更加“坚固可靠”,并且在格式错误时更容易排除故障。

标签: delphi delphi-xe


【解决方案1】:

此类从 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;

【讨论】:

  • 感谢您的发布,您的代码看起来很有趣。从那以后,我在不使用任何 CRC 检查的情况下解决了我最初的问题。我会接受你的回答,但是因为它看起来非常有用,我将不得不更仔细地研究它。谢谢
猜你喜欢
  • 2018-07-26
  • 2016-06-14
  • 2021-06-03
  • 2019-04-20
  • 2019-09-18
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
相关资源
最近更新 更多