unicode Delphi的TStream到TStringList失败
如以下代码的unicode Delphi的TStream到TStringList失败,delphi,unicode,stream,delphi-7,delphi-xe,Delphi,Unicode,Stream,Delphi 7,Delphi Xe,如以下代码的Test2所示,TStringList被转换为TStream,然后TStream被转换回TStringList。但是,在Delphi 7中,Test2与Test1给出的代码相同。在unicode Delphi中,Test2不能给出正确的结果。你能帮我提出什么问题吗 program Project1; {$APPTYPE CONSOLE} {$R *.res} uses Classes, SysUtils; // http://stackoverflow.com/questi
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
将原始字符串
数据原样写入TMemoryStream
,然后原样读回字符串
,这样所有版本的Delphi中的数据都能正确匹配<代码>测试2在Delphi2007和更早版本中工作,原因类似
Test2
在Delphi 2009及更高版本中失败,因为您没有考虑到TStrings.LoadFrom…()
(和TStrings.SaveTo…()
)在这些版本的Delphi中是TEncoding
-感知的。您正在将UTF-16编码的数据写入TMemoryStream
,前面没有BOM,然后您就不会告诉LoadFromStream()
流是UTF-16编码的。它尝试定位BOM表,当找不到BOM表时,它将使用TEncoding.Default
(又称8bit Ansi)加载流(用于向后兼容旧代码)
因此,在本例中,在Delphi 2009及更高版本中加载流数据时,需要指定流数据的正确编码:
DestList.LoadFromStream(AStream, TEncoding.Unicode);
非常感谢您的帮助性回答!旁白:替换
DestList:=nil;尝试DestList:=TStringList.Create代码>带有DestList:=TStringList.Create;试试看
@DavidHeffernan你是说构造器中不会有异常吗?当constructore中可能出现异常时,对Create的调用似乎应该驻留在try finally中。你能帮忙评论一下吗如果构造函数中出现异常,则将调用析构函数,并且不会发生对DestList
的赋值。正确的习惯用法与我的注释一致。请仔细查看注释中的代码。如果构造函数引发,则实际上从未为DestList
赋值。但是,这也发生在try
之前,因此不会执行finally
块。仔细查看一下RTL/VCL源代码,看看哪种格式占主导地位。是的,这是正确的