8

次の状況を取ります。

procedure Test;

var
 Response : String;

begin
 Response := IdHttp.Post(MyUrL, AStream);
 DoSomethingWith(Response);
end;

これで、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;

このソリューションの 1 つの注意点: Delphi は警告 W1058 を発生させます (「文字列」から「RawByteString」への潜在的なデータ損失を伴う暗黙的な文字列キャスト)

私の質問: これはこの問題に対処する正しい方法ですか、それとも TIdHTTP に UnicodeString への変換を行うように指示できますか?

4

2 に答える 2

8

Indy 10 の最新バージョンを使用している場合、オーバーロードされたバージョンの Indy 10 は、データを Unicode にデコードしTIdHTTP.Post()ますが、String デコードに使用される実際の文字セットは、HTTPContent-Type応答ヘッダーが指定するメディア タイプによって異なります。

  1. メディア タイプがapplication/xmlapplication/xml-external-parsed-entityapplication/xml-dtd、またはtext/...タイプではなく、 で終わる場合、XML のプロローグの属性で+xml指定された文字セットが使用されます。encoding文字セットが指定されていない場合は、UTF-8 が使用されます。

  2. それ以外の場合、Content-Type応答ヘッダーで文字セットが指定されている場合は、それが使用されます。

  3. それ以外の場合、メディア タイプがtext/...タイプの場合:

    を。メディア タイプがtext/xmltext/xml-external-parsed-entity、または で終わる場合は+xmlus-asciiが使用されます。

    b. それ以外の場合ISO-8859-1は使用されます。

  4. それ以外の場合は、Indy のデフォルトのエンコーディング (デフォルトでは ASCII) が使用されます。

実際の HTTPContent-Typeヘッダーを確認しないと、状況がどのような状況に陥るかを判断するのは困難です。ISO-8859-1または同様の文字セットが使用されている場合、そのまま返されるUTF-8バイト値を説明する#2または#3bのいずれかに該当するようです。

UTF8ToString()入力としてエンコードされた UTF-8が必要ですが、代わりにRawByteStringエンコードされた UTF-16 を渡しています。UnicodeStringRTL は、変換にデフォルトの Ansi 文字セットを使用して、UTF16->Ansi 変換を実行します。このような変換ではデータが失われる可能性があるため、コンパイラの警告が表示されるのはそのためです。

XML は実際にはバイナリ データ形式であり、文字セット エンコーディングが適用されます。XML パーサーは、XML のエンコーディングが何であるかを認識し、それに応じて生のエンコードされたバイトを解析できる必要があります。encodingそのため、XML はXML プロローグに明示的な属性を持っています。ただし、TIdHTTPXML を としてダウンロードすると、String自動的に Unicode にデコードされますが、それに応じて XML のプロローグはまだ更新されません。

String本当の解決策は、最初から XML を としてダウンロードしないことです。XMLパーサーが元のバイト、元の文字セット宣言などにアクセスできるように、TStream代わりに(TMemoryStreamよりも良い選択です)としてダウンロードします。たとえば、をメソッドに渡すことができます。TStringStreamTStreamTXMLDocument.LoadFromStream()

于 2013-09-16T16:31:13.660 に答える