web-dev-qa-db-ja.com

URLEncoderはスペース文字を変換できません

私は期待している

System.out.println(Java.net.URLEncoder.encode("Hello World", "UTF-8"));

出力するには:

Hello%20World

(20はASCIIスペースの16進コードです)

しかし、私が得るのは:

Hello+World

間違った方法を使用していますか?使用すべき正しい方法は何ですか?

157
Cheok Yan Cheng

これは期待どおりに動作します。 URLEncoderは、HTMLフォームでURLをエンコードする方法に関するHTML仕様を実装します。

javadocs から:

このクラスには、文字列をapplication/x-www-form-urlencoded MIME形式に変換する静的メソッドが含まれています。

および HTML仕様 から:

application/x-www-form-urlencoded

このコンテンツタイプで送信されるフォームは、次のようにエンコードする必要があります。

  1. コントロールの名前と値はエスケープされます。スペース文字は「+」に置き換えられます

あなたはそれを交換する必要があります、例えば:

System.out.println(Java.net.URLEncoder.encode("Hello World", "UTF-8").replace("+", "%20"));
203
dogbane

スペースは、URLでは%20にエンコードされ、フォーム送信データ(コンテンツタイプapplication/x-www-form-urlencoded)では+にエンコードされます。前者が必要です。

Guava を使用:

dependencies {
     compile 'com.google.guava:guava:23.0'
     // or, for Android:
     compile 'com.google.guava:guava:23.0-Android'
}

rlEscapers を使用できます。

String encodedString = UrlEscapers.urlFragmentEscaper().escape(inputString);

String.replaceを使用しないでください。これはスペースのみをエンコードします。代わりにライブラリを使用してください。

42
pyb

このクラスは、パーセントエンコーディングではなくapplication/x-www-form-urlencoded- typeエンコーディングを実行するため、+に置き換えるのが正しい動作です。

Javadocから:

文字列をエンコードする場合、次の規則が適用されます。

  • 英数字「a」から「z」、「A」から「Z」、および「0」から「9」は同じままです。
  • 特殊文字「。」、「-」、「*」、および「_」は同じままです。
  • スペース文字「」はプラス記号「+」に変換されます。
  • 他のすべての文字は安全ではなく、最初に何らかのエンコーディングスキームを使用して1つ以上のバイトに変換されます。次に、各バイトは3文字の文字列「%xy」で表されます。ここで、xyはバイトの2桁の16進表現です。使用する推奨エンコードスキームはUTF-8です。ただし、互換性の理由から、エンコーディングが指定されていない場合、プラットフォームのデフォルトのエンコーディングが使用されます。
25
axtavt

クエリパラメータのエンコード

org.Apache.commons.httpclient.util.URIUtil
    URIUtil.encodeQuery(input);

または、URI内の文字をエスケープする場合

public static String escapeURIPathParam(String input) {
  StringBuilder resultStr = new StringBuilder();
  for (char ch : input.toCharArray()) {
   if (isUnsafe(ch)) {
    resultStr.append('%');
    resultStr.append(toHex(ch / 16));
    resultStr.append(toHex(ch % 16));
   } else{
    resultStr.append(ch);
   }
  }
  return resultStr.toString();
 }

 private static char toHex(int ch) {
  return (char) (ch < 10 ? '0' + ch : 'A' + ch - 10);
 }

 private static boolean isUnsafe(char ch) {
  if (ch > 128 || ch < 0)
   return true;
  return " %$&+,/:;=?@<>#%".indexOf(ch) >= 0;
 }
13
fmucar

Hello+Worldは、ブラウザがGET要求に対してフォームデータ(application/x-www-form-urlencoded)をエンコードする方法であり、これはURIのクエリ部分で一般的に受け入れられているフォームです。

http://Host/path/?message=Hello+World

このリクエストをJavaサーブレットに送信した場合、サーブレットはパラメーター値を正しくデコードします。通常、ここで問題になるのは、エンコードが一致しない場合のみです。

厳密に言えば、HTTP仕様またはURI仕様では、クエリパーツをapplication/x-www-form-urlencodedキーと値のペアを使用してエンコードする必要はありません。クエリ部分は、Webサーバーが受け入れる形式である必要があります。実際には、これが問題になることはほとんどありません。

一般に、URIの他の部分(パスなど)にこのエンコードを使用することは正しくありません。その場合、 RFC 3986 で説明されているエンコードスキームを使用する必要があります。

http://Host/Hello%20World

もっと こちら

11
McDowell

「+」が正しい。本当に%20が必要な場合は、後で自分でPlussesを交換してください。

4
Daniel

他の回答は、手動の文字列置換、 RLEncoder を提示します。これは実際にHTML形式にエンコードされ、Apacheの abandonedRIUtil 、またはGuavaの rlEscapers 。最後のものは、デコーダーを提供しないことを除いて、問題ありません。

Apache Commons Langは、URL形式 rfc3986 に従ってandデコードをエンコードする RLCodec を提供します。

String encoded = new URLCodec().encode(str);
String decoded = new URLCodec().decode(str);

既にSpringを使用している場合は、itsriUtils クラスも使用することもできます。

4
Benny Bottema

Androidでもこれに苦労しており、Uri.encode(String、String)につまずくことができましたが、特定のAndroid(Android.net.Uri)に役立つことがあります。

static String encode(String s、String allow)

https://developer.Android.com/reference/Android/net/Uri.html#encode(Java.lang.String、Java.lang.String)

2
Chrispix

これは私のために働いた

org.Apache.catalina.util.URLEncoder ul = new org.Apache.catalina.util.URLEncoder().encode("MY URL");
2
Hitesh Kumar

かなり古いものの、それにもかかわらず迅速な応答:

SpringはUriUtilsを提供します-これにより、エンコード方法と、URIからどの部分を関連付けるかを指定できます。

encodePathSegment
encodePort
encodeFragment
encodeUriVariables
....

私はすでにSpringを使用しているため、それらを使用します、つまり追加のライブラリは必要ありません!

0
LeO

間違った方法を使用していますか?使用すべき正しい方法は何ですか?

はい、このメソッドJava.net.URLEncoder.encodeは、仕様( source )に従って ""を "20%"に変換するために作成されたものではありません。

スペース文字「」はプラス記号「+」に変換されます。

これは正しい方法ではありませんが、System.out.println(Java.net.URLEncoder.encode("Hello World", "UTF-8").replaceAll("\\+", "%20"));have a Nice day =)に変更できます。

0
Pregunton

Java.net.URIクラスを調べてください。

0