web-dev-qa-db-ja.com

Java URLエンコード:URLEncoder vs. URI

W3 Schools URL encoding webpage を見ると、@%40としてエンコードされ、space%20としてエンコードされているはずです。

私はURLEncoderURIの両方を試しましたが、上記のどちらも適切に行いません:

import Java.net.URI;
import Java.net.URLEncoder;

public class Test {
    public static void main(String[] args) throws Exception {

        // Prints me%40home.com (CORRECT)
        System.out.println(URLEncoder.encode("[email protected]", "UTF-8"));

        // Prints Email+Address (WRONG: Should be Email%20Address)
        System.out.println(URLEncoder.encode("Email Address", "UTF-8"));

        // http://www.home.com/test?Email%[email protected]
        // (WRONG: it has not encoded the @ in the email address)
        URI uri = new URI("http", "www.home.com", "/test", "Email [email protected]", null);
        System.out.println(uri.toString());
    }
}

何らかの理由で、URLEncoderは電子メールアドレスを正しく処理しますがスペースは使用しません。また、URIはスペースの通貨を使用しますが電子メールアドレスは使用しません。

W3schoolsが正しい(またはw3schoolsが間違っている)と一致するように、これら2つのパラメーターをどのようにエンコードする必要がありますか?

19
John Farrelly

@fgeからの答えは正しいと思いますが、W3Schoolsの記事で概説されているエンコーディングに依存するサードパーティのWebサービスを使用していたため、 同じ出力を生成するJavaScriptのencodeURIComponentに相当するJavaからの回答に従いました?

public static String encodeURIComponent(String s) {
    String result;

    try {
        result = URLEncoder.encode(s, "UTF-8")
                .replaceAll("\\+", "%20")
                .replaceAll("\\%21", "!")
                .replaceAll("\\%27", "'")
                .replaceAll("\\%28", "(")
                .replaceAll("\\%29", ")")
                .replaceAll("\\%7E", "~");
    } catch (UnsupportedEncodingException e) {
        result = s;
    }

    return result;
}
35
John Farrelly

URI構文は RFC 3986 で定義されています(クエリ文字列の許容コンテンツはセクション3.4で定義されています)。 JavaのURIは、このRFCに準拠していますが、 Javadoc にいくつかの注意事項が記載されています。

pchar文法規則は以下によって定義されることに気付くでしょう:

pchar = unreserved/pct-encoded/sub-delims/":"/"@"

つまり、@は、クエリ文字列のlegalです。

信頼URI。 willは、正しい「合法的な」ことを行います。

最後に、 RLEncoderのJavadoc を見ると、次のように表示されていることがわかります。

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

これは、notURI仕様で定義されているクエリ文字列と同じものです。

15
fge