web-dev-qa-db-ja.com

TMemoryStreamへの文字列の書き込み

文字列をTMemoryStreamに書き込み、ファイルに保存し、文字列をTMemoryStreamに読み戻すことに関して、ここで多くの議論を読みました。

ここで何が間違っているのかわかりませんが、SaveDataまたはLoadDataのいずれかが間違っています。 SaveDataを呼び出す前に、Titleの値を確認できます。これにより、期待どおりの値が保持されます。ただし、LoadDataを呼び出してTitleの値を確認すると、ガベージです。誰かが私が間違ったことを教えてもらえますか

procedure SaveData(FileName: TFileName);
var
 MemStr: TMemoryStream;
 Title: String;
begin
 MemStr:= TMemoryStream.Create;
try
 MemStr.Seek(0, soFromBeginning);
 WriteStreamStr( MemStr, TItle );
 MemStr.SaveToFile(FileName);
finally
 MemStr.Free;
end;
end;

procedure LoadData(FileName: TFileName);
var
 MemStr: TMemoryStream;
 Title: String;
begin
 MemStr:= TMemoryStream.Create;
 try
  MemStr.LoadFromFile(FileName);
  MemStr.Seek(0, soFromBeginning);
  Title := ReadStreamStr( MemStr );
 finally
   MemStr.Free;
  end;
end;



procedure WriteStreamInt(Stream : TStream; Num : integer);
 {writes an integer to the stream}
begin
 Stream.WriteBuffer(Num, SizeOf(Integer));
end;

procedure WriteStreamStr(Stream : TStream; Str : string);
 {writes a string to the stream}
var
 StrLen : integer;
begin
 {get length of string}
 StrLen := Length(Str);
 {write length of string}
 WriteStreamInt(Stream, StrLen);
 if StrLen > 0 then
 {write characters}
 Stream.Write(Str[1], StrLen);
end;


function ReadStreamInt(Stream : TStream) : integer;
 {returns an integer from stream}
begin
 Stream.ReadBuffer(Result, SizeOf(Integer));
end;

function ReadStreamStr(Stream : TStream) : string;
 {returns a string from the stream}
var
 LenStr : integer;
begin
 Result := '';
 {get length of string}
 LenStr := ReadStreamInt(Stream);
 {set string to get memory}
 SetLength(Result, LenStr);
 {read characters}
 Stream.Read(Result[1], LenStr);
end;
8
JakeSays

使用する場合

_Stream.Write(Str[1], StrLen);
_

最初のStrLenバイトをストリームに書き込んでいます。ただし、(unicode)文字列データは実際にはStrLen * SizeOf(Char)バイトです(char型のサイズを考慮する必要があります)。したがって、以下が機能するはずです。

_Stream.Write(Str[1], StrLen * SizeOf(Str[1]));
_

ストリームからデータを読み戻す場合も同じです。

19
ain