从 Delphi 6 上的 Indy 9 升级到 Delphi 11 上的 Indy 10 后获取空间

sn_*_*a_v 1 xml delphi indy tstream delphi-11-alexandria

我已经从 Delphi 6 迁移到 Delphi 11(64 位版本),并且我正在使用 Indy 和 ZLib 组件。我已经从 Indy 9 迁移到 Indy 10,使用组件发布 API,在此之前我通过以下方式将字符串写入流:

var 
  XML: String; 
  stream: TStream;
begin
  ...
  stream.WriteBuffer(XML[1], Length(XML) * 2);
Run Code Online (Sandbox Code Playgroud)

然后使用 ZLib 组件对其进行压缩。但当它到达服务器时,它会包含消息中每个字母的空格:

< h t m l > u s e r < / h t m l >
Run Code Online (Sandbox Code Playgroud)

关于如何解决这个问题有什么想法吗?

Rem*_*eau 6

自 Delphi 2009 以来,该string类型一直是 UTF-16 编码的UnicodeString。您正在将 a 的原始字符字节string 按原样写入您的TStream,因此您需要将字符串的长度乘以 2,因为SizeOf(Char)是 2 个字节。您看到的空格实际上是 byte ,因为 UTF-16 中的 ASCII 字符#$00高字节设置为零。

但在 Delphi 6 中,string类型改为 8 位AnsiString,并且SizeOf(Char)为 1 个字节。

为了在 Delphi 11 中获得与 Delphi 6 中相同的行为,您需要先将字符转换UnicodeString为编码字节,然后再将它们写入TStream. XML 的默认/首选编码是 UTF-8(但可以是您选择在 XML 的序言中指定的任何其他字符集),例如:

var
  XML: string;
  utf8: UTF8String;
  stream: TStream;
...
utf8 := UTF8String(XML); // use UTF8Encode() in Delphi 6
stream.WriteBuffer(utf8[1], Length(utf8));
Run Code Online (Sandbox Code Playgroud)

或者,Indy 在单元中具有重载WriteStringToStream()函数IdGlobal,这些函数具有可选ADestEncoding参数,例如:

uses
  ..., IdGlobal;

var
  XML: string;
  stream: TStream;
...
WriteStringToStream(stream, XML, IndyTextEncoding_UTF8);
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用 Delphi 自己的类,该类在 Delphi 2009+ 中TStringStream具有可选参数,例如:TEncoding

var
  XML: string;
  stream: TStream;
...
stream := TStringStream.Create(XML, TEncoding.UTF8);
Run Code Online (Sandbox Code Playgroud)

或者,根本不使用 a TStream。Indy 的TIdIOHandler类有一个DefStringEncoding用于文本读/写的属性,它的Write(string)WriteLn(string)方法也有一个可选AByteEncoding参数,例如:

var
  XML: string;
...
Connection.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
...
Connection.IOHandler.Write(XML);
Run Code Online (Sandbox Code Playgroud)

或者:

var
  XML: string;
...
Connection.IOHandler.Write(XML, IndyTextEncoding_UTF8);
Run Code Online (Sandbox Code Playgroud)