Delphi&Indy&utf8?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (171)

我有一个问题,访问到网站whit utf8 charset,例如当我尝试在这个www的accesso

点击例如

所有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 var我发现错误的characthers,例如“名称”的正确值

“名称”:“Mercantour国家公园的粘附区域”,

但在获得Get指令之后

“名称”:“Aire d'adhéithionParc national du Mercantour”,

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

提问于
用户回答回答于

在Delphi 2009+中,包括XE6,string是UTF-16编码的UnicodeString

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

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

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

  • 您可以通过GIdDefaultTextEncodingIdGlobal单位中设置全局变量将Indy的默认字符集设置为UTF-8 : GIdDefaultTextEncoding := encUTF8;
  • 如果属性为空,则可以使用该TIdHTTP.OnHeadersAvailable事件将TIdHTTP.Response.Charset属性更改'utf-8'为。 Web.OnHeadersAvailable := CheckResponseCharset; ... procedure TMyClass.CheckResponseCharset(Sender: TObject; AHeaders: TIdHeaderList; var VContinue: Boolean); var Response: TIdHTTPResponse; begin Response := TIdHTTP(Sender).Response; if IsHeaderMediaType(Response.ContentType, 'application/json') and (Response.Charset = '') then Response.Charset := 'utf-8'; VContinue := True; end;
  • 你可以使用其他重载版本TIdHTTP.Get()来填充输出TStream而不是返回a string。使用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;

扫码关注云+社区

领取腾讯云代金券