私は期待している
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));
出力する:
Hello%20World
(20はスペースのASCII 16進コードです)
しかし、私が得るものは:
Hello+World
間違った方法を使用していますか?私が使用すべき正しい方法は何ですか?
私は期待している
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));
出力する:
Hello%20World
(20はスペースのASCII 16進コードです)
しかし、私が得るものは:
Hello+World
間違った方法を使用していますか?私が使用すべき正しい方法は何ですか?
回答:
これは期待どおりに動作します。はURLEncoder
、HTMLフォームでURLをエンコードする方法のHTML仕様を実装します。
以下からのJavadoc:
このクラスには、文字列をapplication / x-www-form-urlencoded MIME形式に変換するための静的メソッドが含まれています。
そしてHTML仕様から:
application / x-www-form-urlencoded
このコンテンツタイプで送信されるフォームは、次のようにエンコードする必要があります。
- コントロールの名前と値はエスケープされます。スペース文字は「+」に置き換えられます
あなたはそれを交換する必要があります、例えば:
System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replace("+", "%20"));
t.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replace("\\+", "%20"));
スペースは%20
、URLおよび+
フォーム送信データ(コンテンツタイプ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'
}
UrlEscapersを使用できます。
String encodedString = UrlEscapers.urlFragmentEscaper().escape(inputString);
String.replaceを使用しないでください。これはスペースをエンコードするだけです。代わりにライブラリを使用してください。
このクラスは、実行application/x-www-form-urlencoded
従って置き換え、型コードではなくパーセントエンコーディングを有することは
+
正しい動作です。
javadocから:
文字列をエンコードするときは、次のルールが適用されます。
- 英数字の「a」から「z」、「A」から「Z」、および「0」から「9」は変わりません。
- 特殊文字「。」、「-」、「*」、および「_」は同じままです。
- スペース文字「」はプラス記号「+」に変換されます。
- 他のすべての文字は安全ではなく、いくつかのエンコードスキームを使用して最初に1バイト以上に変換されます。次に、各バイトは3文字の文字列「%xy」で表されます。ここで、xyはバイトの2桁の16進数表現です。使用が推奨されるコード化スキームはUTF-8です。ただし、互換性の理由から、エンコーディングが指定されていない場合は、プラットフォームのデフォルトのエンコーディングが使用されます。
url
、スペースがあると解釈されなければなりません%20
。だから私たちはする必要がありurl.replaceAll("\\+", "%20")
ますか?また、JavaScriptの場合は、escape
関数を使用しないでください。encodeURI
またはencodeURIComponent
代わりに使用します。私もそう思っていました。
クエリパラメータのエンコード
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;
}
org.apache.commons.httpclient.util.URIUtil
することが問題を解決する最も効率的な方法のようです!
Hello+World
ブラウザがリクエストのフォームデータ(application/x-www-form-urlencoded
)をエンコードする方法です。GET
これは、URIのクエリ部分で一般的に受け入れられているフォームです。
http://host/path/?message=Hello+World
このリクエストをJavaサーブレットに送信した場合、サーブレットはパラメータ値を正しくデコードします。通常、ここで問題が発生するのは、エンコーディングが一致しない場合のみです。
厳密に言えば、HTTPやURIの仕様では、application/x-www-form-urlencoded
キーと値のペアを使用してクエリ部分をエンコードする必要はありません。クエリ部分は、Webサーバーが受け入れる形式である必要があります。実際には、これが問題になることはほとんどありません。
URIの他の部分(たとえばパス)にこのエンコーディングを使用することは、一般的に正しくありません。その場合は、RFC 3986で説明されているエンコードスキームを使用する必要があります。
http://host/Hello%20World
詳細はこちら。
もう1つの答えは、手動の文字列置換、HTML形式に実際にエンコードするURLEncoder、Apacheの放棄された URIUtil、またはGuavaのUrlEscapersの使用のいずれかです。最後のものは問題ありませんが、デコーダを提供していません。
Apache Commons LangはURLCodecを提供します。これは、 URL形式rfc3986に従ってエンコードおよびデコードします。
String encoded = new URLCodec().encode(str);
String decoded = new URLCodec().decode(str);
すでにSpringを使用し ている場合は、そのUriUtilsクラスを使用することもできます。
「+」は正しいです。本当に%20が必要な場合は、後で自分でPlussesを交換してください。
+
元のテキスト内の文字は、次のようにコード化されることになっています%2B
。
+
コンテキストを知らなくてもそれが正しいと言うことは、少なくとも知識を深めることです。反対票。+または%20をいつ使用するかについては、他の回答を読んでください。
Androidでもこれに苦労していて、Uri.encode(String、String)に遭遇しましたが、Android(android.net.Uri)に固有のものが役立つ場合があります。
static String encode(String s、String allow)
これは私のために働いた
org.apache.catalina.util.URLEncoder ul = new org.apache.catalina.util.URLEncoder().encode("MY URL");
java.net.URIクラスを調べてください。
間違った方法を使用していますか?私が使用すべき正しい方法は何ですか?
はい、このメソッドjava.net.URLEncoder.encodeは、仕様(ソース)に従って「」を「20%」に変換するために作成されていません。
スペース文字「」はプラス記号「+」に変換されます。
これは正しい方法ではありませんが、これを次のSystem.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replaceAll("\\+", "%20"));
ように変更できます。
URLEncoder.encode
)を使用replaceAll
し、この特定のケースでのみ機能するパッチを使用することをお勧めします。代わりに正しいクラスとメソッドを使用してください。他の回答を参照してください。
使用MyUrlEncode.URLencoding(文字列のURL、String型ENC)問題を処理するために、
public class MyUrlEncode {
static BitSet dontNeedEncoding = null;
static final int caseDiff = ('a' - 'A');
static {
dontNeedEncoding = new BitSet(256);
int i;
for (i = 'a'; i <= 'z'; i++) {
dontNeedEncoding.set(i);
}
for (i = 'A'; i <= 'Z'; i++) {
dontNeedEncoding.set(i);
}
for (i = '0'; i <= '9'; i++) {
dontNeedEncoding.set(i);
}
dontNeedEncoding.set('-');
dontNeedEncoding.set('_');
dontNeedEncoding.set('.');
dontNeedEncoding.set('*');
dontNeedEncoding.set('&');
dontNeedEncoding.set('=');
}
public static String char2Unicode(char c) {
if(dontNeedEncoding.get(c)) {
return String.valueOf(c);
}
StringBuffer resultBuffer = new StringBuffer();
resultBuffer.append("%");
char ch = Character.forDigit((c >> 4) & 0xF, 16);
if (Character.isLetter(ch)) {
ch -= caseDiff;
}
resultBuffer.append(ch);
ch = Character.forDigit(c & 0xF, 16);
if (Character.isLetter(ch)) {
ch -= caseDiff;
}
resultBuffer.append(ch);
return resultBuffer.toString();
}
private static String URLEncoding(String url,String enc) throws UnsupportedEncodingException {
StringBuffer stringBuffer = new StringBuffer();
if(!dontNeedEncoding.get('/')) {
dontNeedEncoding.set('/');
}
if(!dontNeedEncoding.get(':')) {
dontNeedEncoding.set(':');
}
byte [] buff = url.getBytes(enc);
for (int i = 0; i < buff.length; i++) {
stringBuffer.append(char2Unicode((char)buff[i]));
}
return stringBuffer.toString();
}
private static String URIEncoding(String uri , String enc) throws UnsupportedEncodingException { //对请求参数进行编码
StringBuffer stringBuffer = new StringBuffer();
if(dontNeedEncoding.get('/')) {
dontNeedEncoding.clear('/');
}
if(dontNeedEncoding.get(':')) {
dontNeedEncoding.clear(':');
}
byte [] buff = uri.getBytes(enc);
for (int i = 0; i < buff.length; i++) {
stringBuffer.append(char2Unicode((char)buff[i]));
}
return stringBuffer.toString();
}
public static String URLencoding(String url , String enc) throws UnsupportedEncodingException {
int index = url.indexOf('?');
StringBuffer result = new StringBuffer();
if(index == -1) {
result.append(URLEncoding(url, enc));
}else {
result.append(URLEncoding(url.substring(0 , index),enc));
result.append("?");
result.append(URIEncoding(url.substring(index+1),enc));
}
return result.toString();
}
}