采取以下情况:
procedure Test;
var
Response : String;
begin
Response := IdHttp.Post(MyUrL, AStream);
DoSomethingWith(Response);
end;
现在网络服务器以 UTF-8 格式返回我的数据。 假设它返回一些包含字符 é 的 UTF-8 XML 。 如果我使用变量 Response 它不包含这个字符,但它是 UTF-8 变体(#C3#A9),所以 Indy 没有解码?
现在我知道如何解决这个问题了:
procedure Test;
var
Response : String;
begin
Response := UTF8ToString(IdHttp.Post(MyUrL, AStream));
DoSomethingWith(Response);
end;
此解决方案的一个警告:Delphi 发出警告 W1058(隐式字符串转换,从“string”到“RawByteString”可能会导致数据丢失)
我的问题:这是处理此问题的正确方法吗?或者我可以指示 TIdHTTP 为我转换为 UnicodeString 吗?
最佳答案
如果您使用的是 Indy 10 的最新版本,则返回 String
的 TIdHTTP.Post()
重载版本可以 将数据解码为 Unicode,但是用于解码的实际字符集取决于 HTTP Content-Type
响应 header 指定的媒体类型:
如果媒体类型是
application/xml
、application/xml-external-parsed-entity
、application/xml-dtd
code>,或者不是text/...
类型,但以+xml
结尾,则在encoding
属性中指定的字符集使用 XML 的序言。如果未指定字符集,则使用 UTF-8。否则,如果
Content-Type
响应 header 指定了字符集,则使用它。否则,如果媒体类型是
text/...
类型,则:a.如果媒体类型为
text/xml
、text/xml-external-parsed-entity
或以+xml
结尾,则使用 us-ascii
。b.否则使用
ISO-8859-1
。否则,将使用 Indy 的默认编码(默认为 ASCII)。
如果没有看到实际的 HTTP Content-Type
header ,就很难知道您的情况属于哪种情况。听起来它属于 #2 或 #3b,如果使用 ISO-8859-1 或类似的字符集,这将说明按原样返回 UTF-8 字节值。
UTF8ToString()
需要 UTF-8 编码的 RawByteString
作为输入,但您要向其传递 UTF-16 编码的 UnicodeString
。在这种情况下,RTL 将执行 UTF16->Ansi 转换,并使用默认的 Ansi 字符集进行转换。这就是您收到编译器警告的原因,因为此类转换可能会丢失数据。
XML 实际上是一种二进制数据格式,受字符集编码的约束。 XML 解析器需要知道 XML 的编码是什么,并能够相应地解析原始编码字节。这就是为什么 XML 在 XML 序言中具有显式的 encoding
属性。但是,当 TIdHTTP
将 XML 作为 String
下载时,尽管它会自动将其解码为 Unicode,但它不会相应地更新 XML 的序言。
真正的解决方案是首先不要将 XML 下载为 String
。将其作为 TStream
下载(TMemoryStream
是比 TStringStream
更好的选择),这样您的 XML 解析器就可以访问原始字节、原始字符集例如,您可以将 TStream
传递给 TXMLDocument.LoadFromStream()
方法。
关于delphi - POST 响应的 TIdHTTP 字符编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18832081/