Delphi Prism:从二进制文件中读取字符串返回奇怪的字符

时间:2013-04-03 19:24:05

标签: string-formatting binaryreader oxygene binarywriter

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

以下是我使用二进制文件写入文件的方式:

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;

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

enter image description here

正如您可以看到或未看到的那样,“GroupHeader.ID”应该只包含“Groupfile”而不是带有垃圾的长字符串。

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

1 个答案:

答案 0 :(得分:2)

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;