Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi-错误的数据写入,然后使用BlockWrite/BlockRead读取_Delphi - Fatal编程技术网

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

Delphi-错误的数据写入,然后使用BlockWrite/BlockRead读取,delphi,Delphi,DelphiTokyo-I并创建一个配置文件。我使用BlockWrite写入配置文件,然后使用BlockRead读取它。当我读字符串时,有点不对劲。我得到的似乎是亚洲字符 我认为问题在于我定义ReadString例程的方式 这是我的写作常规 procedure WriteString(s: ShortString); begin { WriteString } BlockWrite(fil, s, succ(length(s))); end; { WriteString }

DelphiTokyo-I并创建一个配置文件。我使用BlockWrite写入配置文件,然后使用BlockRead读取它。当我读字符串时,有点不对劲。我得到的似乎是亚洲字符

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

这是我的写作常规

  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;
从配置文件中读取的第一个值是一个布尔值,似乎正确读取了该文件。下一个值是一个字符串,它被弄乱了。谢谢你的帮助

下面是完整的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 }

对于短字符串,长度为ord(s[0]),只写入一个字节。但是你把四个字节读入l。所以你不能指望这会奏效。作为修复,您可以将长度分块写入整数或分块读取字节变量l。

a
ShortString
是一种使用1字节长度的8位字符串类型。您正在将
短字符串
正确地写入文件(假设文件的“记录”大小事先已设置为1),但您没有正确地读回它。您正在读取一个4字节的
整数
,而不是一个1字节的
AnsiChar
/
字节
作为字符串长度,然后您正在将8位字符读入一个16位的
UnicodeString
而不是
短字符串

改用这个:

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,因此如果您可以随意更改文件布局,我建议您使用
WriteString()
(Unicode)字符串作为输入,并将其转换为UTF-8进行存储,然后使
ReadString()
执行相反的操作,例如:

procedure WriteString(const s: UnicodeString);
var
  utf: UTF8String;
  len: integer;
begin
  utf := UTF8String(s);
  len := Length(utf);
  BlockWrite(fil, len, sizeof(len));
  BlockWrite(fil, PAnsiChar(utf)^, len);
end;

function ReadString: UnicodeString;
var
  len: integer;
  utf: UTF8String;
begin
  BlockRead(fil, len, sizeof(len));
  SetLength(utf, len);
  BlockRead(fil, PAnsiChar(utf)^, len);
  Result := UnicodeString(utf);
end;

现在是2018年。为什么你还是Pascal IO和ANSI?例如,使用JSON会更容易,并且能够支持Unicode,而不必编写手动解析代码。我没有兴趣告诉你如何修复这个代码。我的强烈建议是扔掉它,用更现代的东西。这很有帮助。非常感谢。您的代码中有一个bug。最后一行应该是。。。结果:=单次破坏(utf);您可能希望更改该值以供将来参考。。。