2009-04-09 84 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。