web-dev-qa-db-ja.com

Delphi 2009でTMemoryStreamを「String」に変換する

Delphi 2009より前のバージョンには次のコードがありました。

function MemoryStreamToString(M : TMemoryStream): String;
var
    NewCapacity: Longint;
begin
    if (M.Size = > 0) or (M.Memory = nil) then
       Result:= '' 
    else
    begin
       if TMemoryStreamProtected(M).Capacity = M.Size then
       begin
           NewCapacity:= M.Size+1;
           TMemoryStreamProtected(M).Realloc(NewCapacity);
       end;
       NullString(M.Memory^)[M.Size]:= #0;
       Result:= StrPas(M.Memory);
    end;
end;

Delphi 2009でUnicodeをサポートするためにこのコードをどのように変換できますか?

29
dmillam

Delphiの古いバージョンであっても、コードは不必要に複雑です。なぜストリームの文字列バージョンを取得すると、ストリームのメモリが強制的に再割り当てされるのですか?

function MemoryStreamToString(M: TMemoryStream): string;
begin
  SetString(Result, PChar(M.Memory), M.Size div SizeOf(Char));
end;

これは、Delphi 2009だけでなく、すべてのDelphiバージョンで機能します。特別な場合を除き、ストリームが空のときに機能します。 SetString は過小評価されている関数です。

Delphi 2009への切り替えでストリームのコンテンツがUnicodeに変更されない場合は、代わりにこの関数を使用する必要があります。

function MemoryStreamToString(M: TMemoryStream): AnsiString;
begin
  SetString(Result, PAnsiChar(M.Memory), M.Size);
end;

これは元のコードと同等ですが、特殊なケースはスキップします。

65
Rob Kennedy

または、TStringStreamを直接使用するようにコードをリファクタリングできますか? TMemoryStreamの代わりに使用でき(同じインターフェイスを持っています)、myStringを呼び出すだけで文字列に「変換」できます:= myStringStream.DataString;

16
John Thomas

「クリーナー」の方法は次のとおりです。

function StreamToString(aStream: TStream): string;
var
  SS: TStringStream;
begin
  if aStream <> nil then
  begin
    SS := TStringStream.Create('');
    try
      SS.CopyFrom(aStream, 0);  // No need to position at 0 nor provide size
      Result := SS.DataString;
    finally
      SS.Free;
    end;
  end else
  begin
    Result := '';
  end;
end;
12
Nick Hodges

私が使う:

function StreamToString(const Stream: TStream; const Encoding: TEncoding): string;
var
  StringBytes: TBytes;
begin
  Stream.Position := 0;
  SetLength(StringBytes, Stream.Size);
  Stream.ReadBuffer(StringBytes, Stream.Size);
  Result := Encoding.GetString(StringBytes);
end;

Delphi XE7でのみテストされています。

4
Ivelin Nikolaev

まだアップグレードしていませんが、私の理解は:

NewCapacity := (M.Size + 1) * SizeOf(Char);
2
Loren Pechtel

あなたを助けることができるTStringStreamと呼ばれる要因があります。 。次のような別のフローのコンテンツをロードできます。

var StringStream: TStringStream; 
begin StringStream := TStringStream.Create(''); 
StringStream.CopyFrom(OtherStream, OtherStream.Size); 
end;

これで、次のような文字列の種類のシリーズに入ることができます:data-stringプロパティはシリーズで構成されていますが、巨大なファイルをファイルストリームにロードしてコピーするイベントなどの大きなオブジェクトではそうしないでくださいこれを独自の文字列ストリームに追加し、それを生成するために努力して、大量のメモリを配置します!

役立つことを願っています

2
Techpromint

適切なサイズの文字ポインターにキャストして、単純に割り当てることができます。

procedure getMemoryStreamAsString( aMS_ : TMemoryStream );
var
  ws : widestring; // in newer Delphi it can be string
  ans : ansistring;
begin
  ws := pwidechar( aMS_.memory );
  // OR
  ans := pansichar( aMS_.memory );
end;
1
The Bitman