-1

SOに関する別の投稿で見つけたこれらの実装を使用しています。ただし、文字列を読み取るときに、ReadStreamStr が余分な文字を文字列に挿入することがあります。そのため、実装をここに投稿して、チェックして承認し、障害がある場合は修正します。

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;

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

ありがとうございました。

4

1 に答える 1

4

文字のInteger前に書かれているのはバイト数ですが、代わりに文字数ReadStreamStr()として解釈しています。D2007 以前では、Ansi は正常に動作します。しかし、D2009 以降では、Unicode は機能しません。D2009+ を使用していると仮定すると、本来の2 倍のメモリが割り当てられますが、その半分だけを埋め、残りの半分は初期化しないままにしておきます。読むときは考慮していません(ただし、書くときは考慮します)。stringstringReadStreamStr()SizeOf(Char)ByteLength()

これを試して:

function ReadStreamStr(Stream: TStream): string;
{ returns a string from the stream }
var
  LenStr: Integer;
  LeftOver: array[0..SizeOf(Char)-1] of Byte;
begin
  Result := '';
  { get length of string }
  LenStr := ReadStreamInt(Stream);
  { set string to get memory }
  SetLength(Result, LenStr div SizeOf(Char));
  if LenStr > 0 then begin
    { read characters }
    Stream.ReadBuffer(Result[1], LenStr);
    { just in case the length was not even }
    LenStr := LenStr mod SizeOf(Char);
    if LenStr > 0 then
      Stream.ReadBuffer(LeftOver[0], LenStr);
  end;
end;

または:

function ReadStreamStr(Stream: TStream): string;
{ returns a string from the stream }
var
  LenStr: Integer;
  Buf: TBytes;
begin
  Result := '';
  { get length of string }
  LenStr := ReadStreamInt(Stream);
  if LenStr > 0 then begin
    { get memory }
    SetLength(Buf, LenStr);
    { read characters }
    Stream.ReadBuffer(Buf[1], LenStr);
    { convert to string }
    Result := TEncoding.Unicode.GetString(Buf);
  end;
end;

いずれにせよ、ストリーム データが D2007 以前で書き込まれ、D2009 以降で読み取られた場合、このコードはそのままでは機能しないことに注意してください。TBytesアプローチに行く必要がありますがTEncoding、 などのデコードに適したものを使用してくださいTEncoding.Default

個人的には、代わりに文字列を最初から UTF-8 として読み書きすることを選択したでしょう。

function ReadStreamStr(Stream: TStream): UTF8String;
{ 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);
  if LenStr > 0 then
    { read characters }
    Stream.Read(PAnsiChar(Result)^, LenStr);
end;

procedure WriteStreamStr(Stream: TStream; const Str: UTF8tring);
{ 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(PAnsiChar(Str)^, StrLen);
end;
于 2013-05-14T01:57:38.003 に答える