Delphi-错误的数据写入,然后使用BlockWrite / BlockRead读取

时间:2018-07-16 17:11:07

标签: delphi

Delphi Tokyo-我并创建一个配置文件。我正在使用BlockWrite写入配置文件,然后使用BlockRead读取它。我在读取字符串时出了点问题。我得到的似乎是亚洲字符...

我认为问题在于定义ReadString例程的方式。

这是我的WriteString例程

  procedure WriteString(s: ShortString);
  begin { WriteString }
    BlockWrite(fil, s, succ(length(s)));
  end; { WriteString }

我的ReadString例程应该给我相同的数据,但事实并非如此。 这是ReadString代码。

 function ReadString: string;
  var
    count: Cardinal;
    l: integer;
  begin
    BlockRead(fil, l, sizeof(integer), count);
    SetLength(Result, l);
    BlockRead(fil, Result[1], l, count);
  end;

从配置文件读取的第一个值是布尔值,并且似乎已正确读取了文件。下一个值是一个字符串,并且被弄乱了。任何帮助表示赞赏。

这里是FULL WriteConfig和ReadConfig例程,以及一个SetConfigValues,它仅创建一些测试数据。

procedure SetConfigValues;
begin
  //
  gCMD_Globals.Load_Table := True;
  gCMD_Globals.DB_Tablename := 'my Test Table';
  gCMD_Globals.Create_Backup := True;
  gCMD_Globals.Delete_Existing_Backup := False;
  gCMD_Globals.Truncate_Existing_Table := True;

  SetLength(gCMD_Detail, 2);

  gCMD_Detail[0].CommandType := 'CMD1';
  gCMD_Detail[0].P1 := 'P11';
  gCMD_Detail[0].P2 := 'P21';
  gCMD_Detail[0].P3 := 'P31';

  gCMD_Detail[1].CommandType := 'CMD1';
  gCMD_Detail[1].P1 := 'P12';
  gCMD_Detail[1].P2 := 'P22';
  gCMD_Detail[1].P3 := 'P32';

end;


procedure WriteConfigFile(FileName: string);
var
  fil: file;
  i: integer;
  num: word; { allows up to 65535 records }
const
  ver: byte = LatestFileVersion;

  procedure WriteString(s: ShortString);
  begin { WriteString }
    BlockWrite(fil, s, succ(length(s)));
  end; { WriteString }

begin { WriteConfigFile }
  assignFile(fil, FileName);
  rewrite(fil, 1); { Create the file }
  BlockWrite(fil, ver, sizeof(ver)); { Write the file version }

  // Now we need to write the gCMD_Globals record
  with gCMD_Globals do
  begin { write the data }

    BlockWrite(fil, Load_Table, sizeof(Load_Table));
    WriteString(DB_Tablename);
    BlockWrite(fil, Create_Backup, sizeof(Create_Backup));
    BlockWrite(fil, Delete_Existing_Backup, sizeof(Delete_Existing_Backup));
    BlockWrite(fil, Truncate_Existing_Table, sizeof(Truncate_Existing_Table));
  end;

  num := length(gCMD_Detail);
  BlockWrite(fil, num, sizeof(num)); { Write the number of records }
  for i := 0 to high(gCMD_Detail) do
    with gCMD_Detail[i] do
    begin { write the data }
      WriteString(CommandType);
      WriteString(P1);
      WriteString(P2);
      WriteString(P3);
    end; { with }
  CloseFile(fil);
end; { WriteConfigFile }

procedure ReadConfigFile(FileName: string);
var
  fil: file;
  i: integer;
  num: word; { allows up to 65535 records }
  ver: byte;

  function ReadString: string;
  var
    count: Cardinal;
    l: integer;
  begin
    BlockRead(fil, l, sizeof(integer), count);
    SetLength(Result, l);
    BlockRead(fil, Result[1], l, count);
  end;


begin { ReadFile }
  assignFile(fil, FileName);
  reset(fil, 1); { Open the file }
  BlockRead(fil, ver, sizeof(ver)); { Read the file version }

  // Now we need to write the gCMD_Globals record
  with gCMD_Globals do
  begin { write the data }

    BlockRead(fil, Load_Table, sizeof(Load_Table));
    DB_Tablename := ReadString;
    BlockRead(fil, Create_Backup, sizeof(Create_Backup));
    BlockRead(fil, Delete_Existing_Backup, sizeof(Delete_Existing_Backup));
    BlockRead(fil, Truncate_Existing_Table, sizeof(Truncate_Existing_Table));
  end;

  BlockRead(fil, num, sizeof(num)); { Read the number of records }
  SetLength(gCMD_Detail, num);
  for i := 0 to high(gCMD_Detail) do
    with gCMD_Detail[i] do
    begin { Read the data }
      CommandType := ReadString;
      P1 := ReadString;
      P2 := ReadString;
      P3 := ReadString;
    end; { with }
  CloseFile(fil);
end; { ReadConfigFile }

2 个答案:

答案 0 :(得分:2)

ShortString是使用1字节长度的8位字符串类型。您正在正确地写入ShortString到文件中(假定文件的“记录”大小已预先设置为1),但是您没有正确地读回它。您正在读取4字节的integer而不是1字节的AnsiChar / Byte作为字符串长度,然后您将8位字符读入16位{{ 1}},而不是UnicodeString

改为使用此:

ShortString

不过,我完全不建议使用function ReadString: string; var len: Byte; s: ShortString; begin BlockRead(fil, len, 1); SetLength(s, len); BlockRead(fil, s[1], len); Result := string(s); end; 。您正在使用Unicode版本的Delphi,因此,如果您可以随意更改文件布局,建议您将ShortString用作WriteString()作为输入,并将其转换为UTF-8进行存储,然后再进行(Unicode)String进行相反操作,例如:

ReadString()

答案 1 :(得分:1)

对于短字符串,长度为ord(s [0]),并且仅写入一个字节。但是,您将四个字节读入l。因此,您不能指望它能起作用。作为解决方法,可以将长度写为整数,也可以读字节变量l。