Nous avions le code suivant avant 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;
Comment pourrions-nous convertir ce code pour prendre en charge Unicode maintenant avec Delphi 2009?
Le code dont vous disposez est inutilement complexe, même pour les anciennes versions de Delphi. Pourquoi la récupération de la version chaîne d'un flux devrait-elle forcer la réallocation de la mémoire du flux, après tout?
function MemoryStreamToString(M: TMemoryStream): string;
begin
SetString(Result, PChar(M.Memory), M.Size div SizeOf(Char));
end;
Cela fonctionne dans toutes les versions de Delphi, pas seulement Delphi 2009. Il fonctionne lorsque le flux est vide sans cas particulier. SetString
est une fonction sous-estimée.
Si le contenu de votre flux ne change pas en Unicode avec votre passage à Delphi 2009, vous devez utiliser cette fonction à la place:
function MemoryStreamToString(M: TMemoryStream): AnsiString;
begin
SetString(Result, PAnsiChar(M.Memory), M.Size);
end;
Cela équivaut à votre code d'origine, mais ignore les cas spéciaux.
Ou peut-être pouvez-vous refactoriser votre code pour utiliser directement un TStringStream directement? Vous pouvez l'utiliser à la place de TMemoryStream (ils ont la même interface) et vous pouvez le "convertir" en une chaîne en appelant simplement myString: = myStringStream.DataString;
Une façon plus "propre" pourrait ê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 uniquement.
Je n'ai pas encore mis à niveau, mais ma compréhension est la suivante:
NewCapacity := (M.Size + 1) * SizeOf(Char);
Il existe un facteur appelé TStringStream
qui pourra vous aider. . .vous pouvez charger le contenu d'un autre flux comme celui-ci:
var StringStream: TStringStream;
begin StringStream := TStringStream.Create('');
StringStream.CopyFrom(OtherStream, OtherStream.Size);
end;
Vous pouvez maintenant entrer dans la série pour un type de chaîne tel que celui-ci: La propriété de chaîne de données comprend la série ... mais n'essayez pas avec de gros objets comme dans le cas où vous chargez un fichier énorme dans un flux de fichiers, puis copiez ceci à votre propre chaîne de caractères et faites un effort pour le produire car cela arrange beaucoup de mémoire!
J'espère que cela pourra aider
Vous pouvez le lancer dans le pointeur de caractère de bonne taille et simplement l'affecter:
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;