首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Delphi & Indy & utf8

Delphi & Indy & utf8
EN

Stack Overflow用户
提问于 2018-10-14 14:59:10
回答 1查看 1.4K关注 0票数 3

我在访问使用utf8字符集的网站时遇到问题,例如,当我尝试访问此www时

Click for example

所有utf8字符的编码都不正确。这是我的访问例程:

var
  Web     : TIdHTTP;
  Sito    : String;
  hIOHand : TIdSSLIOHandlerSocketOpenSSL;

begin
  Url := TIdURI.URLEncode(Url);


  try
    Web := TIdHTTP.Create(nil);
    hIOHand := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    hIOHand.DefStringEncoding := IndyTextEncoding_UTF8;
    hIOHand.SSLOptions.SSLVersions := [sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2,sslvSSLv2,sslvSSLv3,sslvSSLv23];
    Web.IOHandler := hIOHand;
    Web.Request.CharSet := 'utf-8';


    Web.Request.UserAgent := INET_USERAGENT;       //Custom user agent string
    Web.RedirectMaximum := INET_REDIRECT_MAX;      //Maximum redirects
    Web.HandleRedirects := INET_REDIRECT_MAX <> 0; //Handle redirects
    Web.ReadTimeOut := INET_TIMEOUT_SECS * 1000;   //Read timeout msec
    try
      Sito := Web.Get(Url);
      Web.Disconnect;
    except
      on e : exception do
        Sito := 'ERR: ' +Url+#32+e.Message;
    end;
  finally
    Web.Free;
    hIOHand.Free;
  end;

我尝试了所有的解决方案,但在Sito变量中我总是发现错误的字符,例如"name“的正确值是

"name":"Aire d‘’adhésion du Parc national du Mercantour",

但是在Get指令之后,我有

"name":"Aire d‘’adhç©sion du Parc national du Mercantour",

你知道我的错误在哪里吗?谢谢大家!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-14 23:53:04

在包含XE6的Delphi 2009+中,string是一个UTF16编码的UnicodeString

您使用的是返回string的重载版本的TIdHTTP.Get()。它使用响应报告的任何字符集将发送的文本解码为UTF-16。如果文本没有正确解码,很可能意味着响应没有报告正确的字符集。如果使用了错误的字符集,文本将无法正确解码。

实际上,有问题的URL发送的是一个设置为application/json的响应Content-Type标头,而根本没有指定charsetapplication/json的默认字符集是UTF-8,但Indy不知道这一点,因此它最终使用自己的内部默认字符集,而不是UTF-8。这就是当存在非ASCII字符时文本无法正确解码的原因。

在这种情况下,如果您知道字符集始终为UTF-8,则有几种解决方法可供选择:

  • 您可以通过以IdGlobal为单位设置全局GIdDefaultTextEncoding变量,将Indy的默认字符集设置为-8:

GIdDefaultTextEncoding := encUTF8;

  • 如果TIdHTTP.Response.Charset属性为空或不正确,则可以使用TIdHTTP.OnHeadersAvailable事件将其更改为'utf-8'

Web.OnHeadersAvailable := CheckResponseCharset;...procedure Response (发送方: TObject;AHeaders: TIdHeaderList;var VContinue: Boolean);var Response: TIdHTTPResponse;begin Response := TIdHTTP(发送方).Response;if IsHeaderMediaType(Response.ContentType,'application/json') and (Response.Charset = '') then Response.Charset := 'utf-8';VContinue := True;end;

  • 您可以使用其他重载版本的TIdHTTP.Get()填充输出,而不是返回。使用TMemoryStreamTStringStream,您可以使用UTF-8自己解码原始字节:

MStrm := TMemoryStream.Create;try Web.Get(Url,MStrm);MStrm.Position := 0;Sito := ReadStringFromStream(MStrm,IndyTextEncoding_UTF8);finally SStrm.Free;end;

SStrm := TStringStream.Create('',TEncoding.UTF8);try Web.Get(Url,SStrm);Sito := SStrm.DataString;finally SStrm.Free;end;

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52800270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档