簡體   English   中英

對於unicode Delphi,TStream到TStringList失敗

[英]TStream to TStringList fails for unicode Delphi

如下面代碼的Test2所示,TStringList被轉換為TStream,然后TStream被轉換回TStringList。 但是,在Delphi 7中, Test2給出了與Test1相同的功能。 在unicode Delphi中, Test2沒有給出正確的結果。 你能幫忙建議出現什么問題嗎?

program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Classes, SysUtils;

// http://stackoverflow.com/questions/732666
// Converting TMemoryStream to String in Delphi 2009
function MemoryStreamToString(M: TMemoryStream): string;
begin
  SetString(Result, PChar(M.Memory), M.Size div SizeOf(Char));
end;

procedure Test1;
var
  SrcList: TStrings;
  S: String;
  AStream: TStream;
begin
  SrcList := TStringList.Create;
  try
    with SrcList do
    begin
      Add('aa');
      Add('bb');
      Add('cc');
    end;

    S := SrcList.Text;

    AStream := TMemoryStream.Create;
    try
      // AStream.Write(S[1], Length(S));
      // AStream.Write(S[1], Length(S) * SizeOf(Char));
      AStream.Write(Pointer(S)^, Length(S) * SizeOf(Char));

      WriteLn(MemoryStreamToString(TMemoryStream(AStream)));
    finally
      AStream.Free;
    end;
  finally
    SrcList.Free;
  end;
end;

procedure Test2;
var
  SrcList: TStrings;
  S: String;
  AStream: TStream;
  DestList: TStringList;
  I: Integer;
begin
  SrcList := TStringList.Create;
  try
    with SrcList do
    begin
      Add('aa');
      Add('bb');
      Add('cc');
    end;

    S := SrcList.Text;

    AStream := TMemoryStream.Create;
    try
      // AStream.Write(S[1], Length(S));
      // AStream.Write(S[1], Length(S) * SizeOf(Char));
      AStream.Write(Pointer(S)^, Length(S) * SizeOf(Char));

      DestList := TStringList.Create;
      try
        AStream.Position := 0;
        DestList.LoadFromStream(AStream);

        WriteLn(DestList.Text);
      finally
        DestList.Free;
      end;
    finally
      AStream.Free;
    end;
  finally
    SrcList.Free;
  end;
end;

begin
  try
    Test1;
    Test2;
  except
    on E: Exception do
      WriteLn(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Test1將原始String數據按原樣寫入TMemoryStream ,然后將其原樣讀回String ,因此所有版本的Delphi中都能正確匹配。 由於類似的原因, Test2在Delphi 2007及更早版本中運行。

在Delphi 2009及更高版本中, Test2失敗了,因為您沒有考慮到TStrings.LoadFrom...() (以及TStrings.SaveTo...() )在這些版本的Delphi中是TEncoding -aware。 你正在編寫UTF-16編碼數據到TMemoryStream在前面沒有BOM,然后你不告訴LoadFromStream()該流為UTF-16編碼。 它試圖找到一個BOM,當它找不到時,它會使用TEncoding.Default (又名8bit Ansi)加載流(為了向后兼容遺留代碼)。

因此,在此示例中,您需要在Delphi 2009及更高版本中加載流數據時指定正確的流數據編碼:

DestList.LoadFromStream(AStream, TEncoding.Unicode);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM