先日、C++Builder Tipsの記事「URLをエンコード・デコードする」を修正して、TIdURIユニットのURLEncode関数とURLDecode関数を追記した。
以前は、HTTPAppユニットのHTTPEncode関数やHTTPDecode関数を使っていたが、TIdURIユニットの提供する関数を使った方が便利だ。
HTTPEncode関数やHTTPDecode関数は引数全体をエンコード/デコードするが、URLEncode関数とURLDecode関数は完全なURIからエンコード/デコードが必要な部分だけを処理する。
UnicodeString uri = TIdURI::URLEncode(
"http://www.example.com/こんにちは、世界",
TEncoding::UTF8);
//=> http://www.example.com/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E3%80%81%E4%B8%96%E7%95%8C
エンコードしたURLを作成するときは、日本語を含んだURIを作成してから最後にまとめてURLEncode関数でエンコードすればいい。
HTTPEncode関数を使うときは、エンコードが必要な部分を一つ一つエンコードする必要があった。
サンプルいつも参考にさせて頂いてます
utf8の多言語文字列のサーバ送信処理でこのページのコードを参考にさせて頂きましたが
C++BuilderXE3だとIdURI.hppをインクルードしても未解決の外部シンボル’Iduri::TidURL::’~でリンカがエラーを出し
実行ファイルの生成ができませんでした
何か基本的なところの問題とは思いますがアドバイスをお願いします
C++Builder XE3の新規コンソールアプリケーションでターゲットフレームワークに「FireMonkey」と「ビジュアルコンポーネントライブラリ」をそれぞれ試してみましたが、問題なく実行できました。
「ビジュアルコンポーネントライブラリ」
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
#pragma argsused
#include <tchar.h>
#include <stdio.h>
#include <iostream>
#include <System.hpp>
#include <IdURI.hpp>
int _tmain(int argc, _TCHAR* argv[])
{
UnicodeString uri = TIdURI::URLEncode(
"http://www.example.com/こんにちは、世界“,
TEncoding::UTF8);
std::wcout << uri.c_str() << std::endl;
return 0;
}
「FireMonkey」
#include <fmx.h>
#pragma hdrstop
#pragma argsused
#include <tchar.h>
#include <stdio.h>
#include <iostream>
#include <System.hpp>
#include <IdURI.hpp>
int _tmain(int argc, _TCHAR* argv[])
{
UnicodeString uri = TIdURI::URLEncode(
"http://www.example.com/こんにちは、世界“,
TEncoding::UTF8);
std::wcout << uri.c_str() << std::endl;
return 0;
}
問題動いたとのコメントでしたのでこちらでも新規VCLアプリケーションで上記コードのみを追加したところ
同じようにコンパイルが通りました
パッケージの指定の違いかと思いテストプログラムに同じ設定をしたけどエラーが出ず
またエラーが発生したフォームをテストプログラムに追加しても再現しませんでした
プロジェクトの設定がおかしくなってる可能性が高いので新規で作り直してみます
回答ありがとうございました
作り直しをしてテストしてみました
URLEncodeはプロトコル指定が必須だったんですね・・・
目的が多言語データをutf8でpostするためのEncode処理だったのでちょっと外してました
Web.HTTPApp.HTTPEncodeが多言語のutf8文字列をうまくEncodeしてくれなかったことがスタートでした
申し訳ありませんがもし何か情報または間違っている点がありましたらお願いします
RawByteString PostUtf8 = HTTPEncode(UTF16ToUTF8(UnicodeMltUtf16Str));
こんな感じでどうでしょうか。
UnicodeString s = “こんにちは、世界”;
UTF8String utf8 = s; //UTF8に変換
RawByteString raw(utf8.c_str()); //RawByteStringに変換
RawByteString PostUtf8 = HTTPEncode(raw); //エンコード
RawByteStringへの変換の仕方が参考になりました
このコードで目的にかなり近寄ったのですがやはり多言語データや長い文字列を使用した場合
HTTPEncodeで一部で誤変換が行われているようです
中国語
正:%E9%A9%BE%E9%A9%B6%E5%AE%A4%E8%A3%85%E9%85%8D%0D%0A
×:%E9%A9%BE%E9%A9%B6%E5%AE%A4%E8%A3%81E%81E
アラビア語
正:%E0%B8%8A%E0%B8%B8%E0%B8%94%E0%B8%A2%E0%B8%B2%E0%B8%87%E0%B8%AB%E0%B8%99%E0%B9%89%E0%B8%B2
×:%E0%B8%8A%E0%B8%B8%E0%B8%94%E0%B8%A2%E0%B8%B2%E0%B8%81E%B8%AB%E0%B8%99%E0%B9%89%E0%B8%B2
こんにちは、世界ほにゃらら
正:%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E3%80%81%E4%B8%96%E7%95%8C%E3%81%BB%E3%81%AB%E3%82%83%E3%82%89%E3%82%89
×:%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E3%80%81%E4%B8%96%E7%95%8C%E3%81%BB%E3%81%AB%E3%82%81E%82%89%E3%82%81E
もし環境側でチェックすべき項目がありましたらアドバイスをお願いします
同じRawStringを自前で全バイトデータをエンコードしたら正しい値になりました
やはりXE3のHTTPEncodeの処理側の問題ですね
もし機会がありましたら問題点として提示してください
では失礼します
HTTPEncodeは引数にAnsiStringをとるので、暗黙に文字コードが変換されるのかもしれませんね。
英語は苦手なので私の方からQCの登録はいたしません。ご了承ください。