Conversión de TMemoryStream a ''Cadena'' en Delphi 2009
string unicode (5)
¿O quizás puede refactorizar su código para usar directamente un TStringStream directamente? Puede usarlo en lugar de TMemoryStream (tienen la misma interfaz) y puede ''convertirlo'' a una cadena simplemente llamando a myString: = myStringStream.DataString;
Teníamos el siguiente código antes de 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>
¿Cómo podríamos convertir este código para soportar Unicode ahora con Delphi 2009?
El código que tienes es innecesariamente complejo, incluso para versiones anteriores de Delphi. ¿Por qué la búsqueda de la versión de cadena de una secuencia obliga a reasignar la memoria de la secuencia, después de todo?
function MemoryStreamToString(M: TMemoryStream): string;
begin
SetString(Result, PChar(M.Memory), M.Size div SizeOf(Char));
end;
Eso funciona en todas las versiones Delphi, no solo en Delphi 2009. Funciona cuando la transmisión está vacía sin ningún caso especial. SetString
es una función poco apreciada.
Si el contenido de tu transmisión no cambia a Unicode con tu cambio a Delphi 2009, entonces debes usar esta función:
function MemoryStreamToString(M: TMemoryStream): AnsiString;
begin
SetString(Result, PAnsiChar(M.Memory), M.Size);
end;
Eso es equivalente a su código original, pero omite los casos especiales.
No he actualizado aún, pero mi entendimiento es:
NewCapacity := (M.Size + 1) * SizeOf(Char);
Una manera "más limpia" podría ser:
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;
Yo suelo:
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;
Ha sido probado solo con Delphi XE7.