who*_*ddy 7 delphi unicode utf-8 idhttp delphi-xe
采取以下情况:
procedure Test;
var
Response : String;
begin
Response := IdHttp.Post(MyUrL, AStream);
DoSomethingWith(Response);
end;
Run Code Online (Sandbox Code Playgroud)
现在,web服务器以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;
Run Code Online (Sandbox Code Playgroud)
这个解决方案的一个警告:Delphi引发警告W1058(隐式字符串转换,潜在的数据丢失从'string'到'RawByteString')
我的问题:这是处理这个问题的正确方法,还是我可以指示TIdHTTP为我转换为UnicodeString?
如果您使用的是先进的最新版本印10,随后的的重载版本TIdHTTP.Post(),它返回一个String 没有解码数据为Unicode,但用于解码的实际字符集取决于什么媒体类型的HTTP Content-Type响应头规定:
如果媒体类型是application/xml,application/xml-external-parsed-entity,application/xml-dtd,或不是一个text/...类型,但确实与结束+xml,然后以指定的字符集encoding被使用的XML的序言的属性.如果未指定charset,则使用UTF-8.
否则,如果Content-Type响应头指定了一个字符集,则使用它.
否则,如果媒体类型是text/...类型,则:
一个.如果媒体类型是text/xml,text/xml-external-parsed-entity或结束+xml,则us-ascii使用.
湾 否则ISO-8859-1使用.
否则,使用Indy的默认编码(默认为ASCII).
如果没有看到实际的HTTP Content-Type标头,很难知道您的情况属于哪种情况.听起来它正在落入#2或#3b,这将考虑到原样返回的UTF-8字节值,如果使用ISO-8859-1或类似的字符集.
UTF8ToString()期望UTF-8编码RawByteString为输入,但您传递的是UTF-16编码UnicodeString.在这种情况下,RTL将执行UTF16-> Ansi转换,使用默认的Ansi字符集进行转换.这就是你得到编译器警告的原因,因为这样的转换可能会丢失数据.
XML实际上是一种二进制数据格式,受charset编码的限制.XML解析器需要知道XML的编码是什么,并且能够相应地解析原始编码的字节.这就是XML encoding在XML序言中具有明确属性的原因.然而,当TIdHTTP下载XML作为String,虽然它自动将其解码为Unicode,它不尚未更新XML的相应的Prolog.
真正的解决方案是首先不要将XML下载为String.将其下载为TStream替代(TMemoryStream比它更好的选择TStringStream),以便您的XML解析器可以访问原始字节,原始字符集声明等.例如,您可以将其传递TStream给TXMLDocument.LoadFromStream()方法.
| 归档时间: |
|
| 查看次数: |
11144 次 |
| 最近记录: |