Delphi Prism: чтение строки из двоичного файла возвращает странные символы

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

Вот как я пишу в файл с помощью 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" с мусором в ней.

Итак, что я делаю неправильно? Это ошибка формата строки?


person ThN    schedule 03.04.2013    source источник


Ответы (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;
person Remy Lebeau    schedule 03.04.2013
comment
Спасибо, Реми..... Как я это пропустил? Я не знаю. Может быть, я слишком устал смотреть на экран компьютера весь день.... Еще раз спасибо. - person ThN; 03.04.2013
comment
Я действительно хочу поблагодарить Stackoverflow.com за всю помощь, которую я получаю. Сайт очень помог мне понять мой собственный код. - person ThN; 03.04.2013