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?
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.
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;
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;
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.
Je n'ai pas encore mis à jour, mais ma compréhension est:
NewCapacity := (M.Size + 1) * SizeOf(Char);