Кодировка символов TIdHTTP ответа POST
возьмем следующую ситуацию:
procedure Test;
var
Response : String;
begin
Response := IdHttp.Post(MyUrL, AStream);
DoSomethingWith(Response);
end;
теперь веб-сервер возвращает мне данные в UTF-8. Предположим, он возвращает мне некоторый XML UTF-8, содержащий символ é. Если я использую переменную 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 для меня?
2 ответов
если вы используете последнюю версию Indy 10, то перегруженная версия TIdHTTP.Post()
что возвращает String
тут декодируйте данные в Unicode, однако фактическая кодировка, используемая для декодирования, зависит от типа носителя HTTP Content-Type
заголовок ответа указывает:
если тип носителя либо
application/xml
,application/xml-external-parsed-entity
,application/xml-dtd
или неtext/...
тип, но заканчивается на+xml
, затем кодировка, указанная вencoding
используется атрибут пролога XML. Если кодировка не указана, используется UTF-8.в противном случае, если
Content-Type
заголовок ответа задает кодировку, затем она используется.-
в противном случае, если тип носителя-это
text/...
тип, то:a. если тип носителя
text/xml
,text/xml-external-parsed-entity
и заканчивается+xml
, потом это.б. в противном случае
ISO-8859-1
is используемый. в противном случае используется кодировка Indy по умолчанию (ASCII по умолчанию).
не видя фактического HTTP Content-Type
заголовок, трудно понять, в какое состояние попадает ваша ситуация. Похоже, что он попадает в #2 или #3b, что объясняет байтовые значения UTF-8, возвращаемые как есть, если ISO-8859-1
или используется аналогичная кодировка.
UTF8ToString()
ожидает кодировку UTF-8 RawByteString
как вход, но вы передаете ему кодировку UTF-16 UnicodeString
вместо. RTL будет выполнять преобразование UTF16 - >Ansi в этой ситуации, используя кодировку Ansi по умолчанию для преобразования. Вот почему вы получаете предупреждение компилятора, потому что такое преобразование может потерять данные.
XML-это действительно двоичный формат данных с учетом кодировок кодировок. Синтаксический анализатор XML должен знать, что такое кодировка XML, и иметь возможность анализировать необработанные закодированные байты соответственно. Вот почему XML имеет явное encoding
атрибут прямо в XML-пролог. Однако, когда TIdHTTP
загружает XML как String
, хотя он автоматически декодирует его в Unicode, он не но обновите пролог XML соответственно.
реальное решение - не загружать XML как String
в первую очередь. Загрузите его как TStream
вместо (TMemoryStream
лучше, чем TStringStream
) таким образом, ваш синтаксический анализатор XML имеет доступ к исходным байтам, оригинальному объявлению кодировки и т. д. Вы можете пройти TStream
до TXMLDocument.LoadFromStream()
метод, например.
вы можете сделать это:
var
sstream: TStringStream;
begin
sstream := TStringStream.Create('', TEncoding.UTF8);
try
IdHttp.Post(MyUrL, AStream, sstream);
DoSomethingWith(sstream.DataString);
finally
sstream.Free;
end;