作者:全程解密_785 | 来源:互联网 | 2022-12-02 12:49
我有一个问题,访问到网站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,例如"名称"的正确值
"名称":"A dd'adhésionduParc national du Mercantour",
但在获得Get指令之后
"名称":"Aire d'adhéithionParc national du Mercantour",
你知道我的错误在哪里吗?谢谢你们!
1> Remy Lebeau..:
在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,您可以选择以下几种解决方法:
您可以通过GIdDefaultTextEncoding
在IdGlobal
单位中设置全局变量将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
.使用TMemoryStream
或TStringStream
,您可以使用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;