2009-04-09 83 views
26

转换内存流为“字符串”我们有下面的代码之前,德尔福2009年:在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> 

我们如何把这段代码转换德尔福2009年为支持Unicode现在?

回答

62

即使对于较老的Delphi版本,您拥有的代码也不必要的复杂。为什么要获取流的字符串版本迫使流的内存重新分配?

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

适用于所有德尔福版本,不仅仅是德尔福2009年。它适用于流没有任何特殊情况时为空。 SetString是一个低估功能。

如果流的内容不会改变你切换到2009年德尔福为Unicode,那么你应该使用这个功能来代替:

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

这相当于原来的代码,但跳过特殊情况。

+1

我已经做了很多Delphi内存的东西,但我没有听说过SetString,总是使用SetLength(dest,length)和Move(src,@(dest [1]),length);其中SetString也可以(将它称为_LStrFromPCharLen) – 2009-04-09 08:39:45

+0

类型化为PChar,不应该产生任何问题。 – 2009-04-09 12:52:31

+0

指针与所有内容兼容。您需要进行类型转换的唯一原因是编译器在重载解析时遇到问题。 – 2009-04-09 14:18:40

2

我还没有升级,但我的理解是:

NewCapacity := (M.Size + 1) * SizeOf(Char); 
16

或者你可以重构代码以直接直接使用TStringStream?你可以使用它来代替TMemoryStream(它们具有相同的接口),只需调用myString:= myStringStream.DataString;就可以将它“转换”为一个字符串。

+1

确实,这是首先想到的东西。为什么不创建一个TStringStream,加载它的内存流,并返回数据串? – 2009-04-09 06:51:22

12

“更清洁” 的方法可能是:

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; 
3

我用:

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; 

它已与德尔福只测试XE7。