あるURLがあったとします。
http://example.com/query?q=
があり、ユーザーが入力した以下のようなクエリがあるとします。
ランダムワード £500 銀行 $
結果として、適切にエンコードされたURLを取得したい。
http://example.com/query?q=random%20word%20%A3500%20bank%20%24
これを実現するにはどのような方法がありますか?URLEncoder`やURI/URLオブジェクトの作成を試みましたが、どれもうまくいきませんでした。
URLEncoder
を使用するのが良いでしょう。留意すべき点は、URL全体ではなく、個々のクエリストリングパラメータ名や値のみをエンコードすることであり、クエリストリングパラメータセパレータ文字 &
やパラメータ名-値セパレータ文字 =
もエンコードしないことです。
String q = "random word £500 bank $";
String url = "http://example.com/query?q=" + URLEncoder.encode(q, "UTF-8");
クエリパラメータ内のスペースは +
で表され、%20
ではなく、正当に有効であることに注意してください。20は通常、クエリ文字列(
?の後の部分)ではなく、URI自体(URI-クエリ文字列のセパレータ文字
?`の前の部分)でスペースを表現するために使用されます。
また、2つの encode()
メソッドがあることにも注意してください。1つは charset 引数なし、もう1つは charset 引数ありです。charset 引数なしのものは非推奨です。決して使用せず、常に charset 引数を指定してください。javadoc]2では、RFC3986やW3Cで義務付けられているように、UTF-8のエンコーディングを使用することを明示的に推奨しています。
それ以外の文字は安全ではなく、まず何らかのエンコーディング方式で1つ以上のバイトに変換されます。このとき、各バイトは3文字の文字列 "%xy"で表され、xyはそのバイトの2桁の16進数表現です。推奨されるエンコーディング方式はUTF-8です。ただし、互換性の観点から、エンコーディングが指定されていない場合は、そのプラットフォームのデフォルトのエンコーディングが使用されます。
私は URLEncoder
は使いません。名前が間違っていること(URLEncoder
はURLとは関係ありません)、効率が悪いこと(Builderの代わりにStringBuffer
を使いますし、他にもいくつか遅いことをしています)に加えて、それを台無しにするのがあまりにも簡単です。
代わりに私はURIBuilder
やSpring's org.springframework.web.util.UriUtils.encodeQuery
やCommons Apache HttpClient
を使います。
理由は、クエリパラメータ名(つまりBalusC'の回答 q
)をパラメータ値とは異なる形でエスケープする必要があるからです。
上記の唯一の欠点は(私が痛感したことですが)、URL'sはURI'sの真のサブセットではないということです。
サンプルコードです。
import org.apache.http.client.utils.URIBuilder;
URIBuilder ub = new URIBuilder("http://example.com/query");
ub.addParameter("q", "random word £500 bank \$");
String url = ub.toString();
// Result: http://example.com/query?q=random+word+%C2%A3500+bank+%24
*他の回答にリンクしているだけなので、これをコミュニティ・ウィキとしてマークしました。ご自由に編集してください。