【问题标题】:Delphi Prism: Reading a string from binary file returns with wierd charactersDelphi Prism:从二进制文件中读取字符串返回奇怪的字符
【发布时间】:2013-04-03 19:24:04
【问题描述】:

我正在将字符串写入文件并使用 binarywriter 和 binaryreader 将其读回。当字符串被读回时,它看起来很有趣而且很长。我不知道它为什么这样做。

这是我使用 binarywriter 写入文件的方法:

TFileHeader = Record
        ID:String;
        version:SmallInt;
end;

method WriteGroups(fname:string; cg:ArrayList);
var
  strm : BinaryWriter;
  i:integer;
  cnt:Integer;
  GroupHeader:TFileHeader;
begin    
  GroupHeader.ID:='GroupFile'; <<<-----I am having problem with this string.
  GroupHeader.version:=6;

  if Environment.OSVersion.Platform = System.PlatformID.Unix then
     fname := baseDir +'/calgroup.dat'
  else
     fname := baseDir +'\calgroup.dat';

  if cg.Count > 0 then
  begin
    strm := new BinaryWriter(File.Create(fname));

    cnt := cg.Count;
    strm.Write(GroupHeader.version);
    strm.Write(GroupHeader.ID);
    strm.Write(cnt);

    for i := 0 to cnt - 1 do
    begin
      TCalGroup(cg[i]).WriteMGroup(strm);
    end;
    strm.Close;
  end;
end;

这是我使用 BinaryReader 从文件中读取的方式:

method ReadGroups(fname:string; cg:ArrayList);
var
  strm : BinaryReader;
  GroupHeader:TFileHeader;
  cnt:SmallInt;
  i:integer;
  cgp:TMagiKalCalGroup;
begin
  GroupHeader.ID :='';
  GroupHeader.version := 0;

  if Environment.OSVersion.Platform = System.PlatformID.Unix then
     fname := baseDir +'/calgroup.dat'
  else
     fname := baseDir +'\calgroup.dat';

  if File.Exists(fname) then
  begin
    ClearGroups(cg);
    strm := new BinaryReader(file.OpenRead(fname));

    GroupHeader.version:=strm.ReadInt32;
    GroupHeader.ID := strm.ReadString; <-----Here is the problem. See the image below..

    if ((GroupHeader.ID='') or (GroupHeader.version>100)) then
    begin
        strm.Close;
        Exit;
    end;

    if (GroupHeader.version<5) then
    begin
      strm.Close;
      exit;
    end;

    cnt := strm.ReadInt16;

    for i := 0 to cnt - 1 do
    begin
      reformat:=false;
      cgp := new TMagiKalCalGroup('New Grp');
      cgp.ReadMGroup(Strm);
      cgp.UpdateDateTime(System.DateTime.Now);
      cg.Add(cgp);
    end;
    //strm.Free;
    strm.Close;
  end;
end;

这是我在调试代码时看到的:

如你所见,“GroupHeader.ID”应该只包含“Groupfile”而不是包含垃圾的长字符串。

那么,我做错了什么?这是字符串格式错误吗?

【问题讨论】:

    标签: string-formatting binaryreader oxygene binarywriter


    【解决方案1】:

    Smallint 是一个 16 位值。读取文件时,您将该值作为 32 位值而不是 16 位值读取,因此您最终会读取一些属于存储字符串长度的字节。然后,当您读取字符串时,字符串字符的前 2 个字节被解释为字符串长度的一部分,这就是您最终得到垃圾的原因。

    您在阅读组时遇到了类似的逻辑错误。 Integer 是一个 32 位值。读取组计数时,您将其读取为 16 位值,这意味着您的组读取将关闭 2 个字节并且也会损坏。

    您需要在 ReadGroups() 函数中更改这些行:

    cnt: Smallint;
    ...
    GroupHeader.version:=strm.ReadInt32;
    ...
    cnt := strm.ReadInt16;
    

    改为:

    cnt: Integer;
    ...
    GroupHeader.version := strm.ReadInt16;
    ...
    cnt := strm.ReadInt32;
    

    【讨论】:

    • 谢谢 Remy .....我怎么会错过呢?我不知道。也许我整天盯着电脑屏幕太累了……再次感谢。
    • 我真的要感谢 Stackoverflow.com 为我提供的所有帮助。该网站在帮助我理解自己的代码方面非常有帮助。
    猜你喜欢
    • 1970-01-01
    • 2014-06-18
    • 2012-09-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 2019-11-14
    相关资源
    最近更新 更多