Conversion TMemoryStream en 'String' dans Delphi 2009

nous avions le code suivant avant Delphi 2009:

<span style="font: 10pt Courier New;"><span class="pas1-reservedword">function</span><span class="pas1-space"> </span><span class="pas1-identifier">MemoryStreamToString(M:</span><span class="pas1-space"> </span><span class="pas1-identifier">TMemoryStream):</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  </span><span class="pas1-identifier">NewCapacity:</span><span class="pas1-space"> </span><span class="pas1-identifier">Longint;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">(M.Size</span><span class="pas1-space"> </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-number">0)</span><span class="pas1-space"> </span><span class="pas1-reservedword">or</span><span class="pas1-space"> </span><span class="pas1-symbol">(M.Memory</span><span class="pas1-space"> </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">nil</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space">    </span><span class="pas1-identifier">Result:=</span><span class="pas1-space"> </span><span class="pas1-string">''
</span><span class="pas1-space">  </span><span class="pas1-reservedword">else
</span><span class="pas1-space">  </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">    </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-identifier">TMemoryStreamProtected(M).Capacity</span><span class="pas1-space"> </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-identifier">M.Size</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space">    </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">      </span><span class="pas1-identifier">NewCapacity:=</span><span class="pas1-space"> </span><span class="pas1-identifier">M.Size+1;
</span><span class="pas1-space">      </span><span class="pas1-identifier">TMemoryStreamProtected(M).Realloc(NewCapacity);
</span><span class="pas1-space">    </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-identifier">NullString(M.Memory^)[M.Size]:=</span><span class="pas1-space"> </span><span class="pas1-character">#0;
</span><span class="pas1-space">    </span><span class="pas1-identifier">Result:=</span><span class="pas1-space"> </span><span class="pas1-identifier">StrPas(M.Memory);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span></span>

Comment pourrions-nous convertir ce code pour supporter Unicode maintenant avec Delphi 2009?

26
demandé sur Peter Mortensen 2009-04-09 07:24:23

5 réponses

le code que vous avez est inutilement complexe, même pour les anciennes versions de Delphi. Pourquoi récupérer la version string d'un stream force-t-il la mémoire du stream à être réattribuée, après tout?

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

qui fonctionne dans toutes les versions Delphi, pas seulement Delphi 2009. Cela fonctionne quand le flux est vide sans aucun cas particulier. SetString est une fonction sous-estimée.

Si le contenu de votre flux ne sont pas passer à Unicode avec votre commutateur à Delphi 2009, alors vous devriez utiliser cette fonction à la place:

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

c'est l'équivalent de votre code original, mais oublie les cas spéciaux.

62
répondu Rob Kennedy 2012-12-12 22:06:55

ou peut-être Pouvez-vous reformuler votre code pour utiliser directement un TStringStream? Vous pouvez l'utiliser à la place de TMemoryStream (ils ont la même interface) et vous pouvez le "convertir" en chaîne de caractères en appelant simplement myString := myStringStream.Datatring;

16
répondu John Thomas 2009-04-09 05:51:17

Un "nettoyeur" peut-être:

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
répondu Nick Hodges 2011-06-22 10:12:04

j'utilise:

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;

il a été testé avec Delphi XE7 seulement.

4
répondu Ivelin Nikolaev 2014-12-31 01:33:43

Je n'ai pas encore mis à jour, mais ma compréhension est:

NewCapacity := (M.Size + 1) * SizeOf(Char);
2
répondu Loren Pechtel 2017-01-17 18:04:08