URLをURIにエンコードするのに問題があります。
mUrl = "A string url that needs to be encoded for use in a new HttpGet()";
URL url = new URL(mUrl);
URI uri = new URI(url.getProtocol(), url.getAuthority(), url.getPath(),
url.getQuery(), null);
これは、次のURLに対して私が期待することを行いません。
文字列を渡す:
次のようになります:
壊れています。たとえば、%3D
は%253D
に変換されます。文字列に既に含まれている%に不思議なことをしているようです。
何が起こっているのですか、ここで何が間違っているのですか?
最初に(エスケープされた)文字列をURL
クラスに入れます。それは何もエスケープしません。次に、URL
のセクションを引き出します。これにより、何も処理せずにセクションが返されます(そのため、それらを配置したときにエスケープされていたため、エスケープされています)。最後に、 マルチ引数コンストラクタ を使用して、セクションをURI
クラスに配置します。このコンストラクタは、パーセンテージを使用してURIコンポーネントをエンコードするように指定されています。
したがって、たとえば、「:
」が「%3A
」(良好)になり、「%3A
」が「%253A
」(不良)になるのは、この最後のステップです。 。すでにエンコードされているURLを入力しているため*、再度エンコードする必要はありません。
したがって、URI
の- 単一引数コンストラクタ はあなたの友達です。何もエスケープせず、事前にエスケープされた文字列を渡す必要があります。したがって、URL
はまったく必要ありません。
mUrl = "A string url is already percent-encoded for use in a new HttpGet()";
URI uri = new URI(mUrl);
*唯一の問題は、URLがパーセントでエンコードされていない場合と、そうでない場合があります。次に、より大きな問題があります。プログラムが常にエンコードされているURLで開始するのか、エンコードが必要なURLで開始するのかを決定する必要があります。
パーセントエンコードされていない完全なURLとしてそのようなことはありませんがあることに注意してください。たとえば、完全なURL "http://example.com/bob&co
"を取得して、どういうわけかそれを適切にエンコードされたURL "http://example.com/bob%26co
"に変換することはできません。エスケープする必要があります)と文字(どちらにする必要がありますか)?これが、URI
の単一引数形式では、文字列がすでにエスケープされている必要がある理由です。エスケープされていない文字列がある場合は、パーセントエンコードする必要がありますbefore完全なURL構文に挿入します。これが、URI
の複数引数コンストラクターが役立ちます。
編集:元のコードがフラグメントを破棄するという事実を見逃しました。 URLのフラグメント(またはその他の部分)を削除する場合は、上記のようにURI
を作成し、必要に応じてすべての部分を引き出します(これらはdecodedになります)。通常の文字列に)、次にそれらをURI
マルチ引数コンストラクターに戻します(URIコンポーネントとしてre-encodedになります):
uri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(),
uri.getPath(), uri.getQuery(), null) // Remove fragment
%3d手段-> =(等しい)
そして
%253D-> =(Equal)10進数6hex(バイト)3D
%253D CGIの16進インジケータ:%3D
URL
クラスは、URLを解析したときに%シーケンスをデコードしませんでしたが、URI
クラスはそれらを(再度)エンコードしています。 URI
を使用して、URL文字列を解析します。
Javadocs:
http://download.Oracle.com/javase/6/docs/api/Java/net/URL.html
RFC2396で定義されているエスケープメカニズムに従って、URLクラス自体はURLコンポーネントをエンコードまたはデコードしません 。 URLを呼び出す前にエスケープする必要があるフィールドをエンコードし、URLから返されたエスケープされたフィールドをデコードすることは、呼び出し元の責任です。さらに、URLにはURLエスケープの知識がないため、同じURLのエンコードされた形式とデコードされた形式の等価性は認識されません。たとえば、次の2つのURL:
http://foo.com/hello world/ and http://foo.com/hello%20world
互いに等しくないと見なされます。 URIクラスは、特定の状況でコンポーネントフィールドのエスケープを実行することに注意してください。
URLのエンコードとデコードを管理するための推奨される方法は、URIを使用して、これら2つのクラスは、toURI()とURI.toURL()を使用しています。