[java] 공백 문자를 번역 할 수없는 URLEncoder

나는 기대하고있다

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

이 컨텐츠 유형으로 제출 된 양식은 다음과 같이 인코딩되어야합니다.

  1. 제어 이름 및 값이 이스케이프됩니다. 공백 문자는`+ ‘로 대체됩니다

다음과 같이 교체해야합니다.

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


답변

공백은 %20URL 로 인코딩 되고+ 제출 된 데이터 (콘텐츠 유형 application / x-www-form-urlencoded)로 인코딩됩니다. 당신은 전자가 필요합니다.

구아바 사용 :

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는 퍼센트 인코딩이 아닌 -type 인코딩을 수행 하므로으로 대체 하는 +것이 올바른 동작입니다.

javadoc에서 :

문자열을 인코딩 할 때 다음 규칙이 적용됩니다.

  • 영숫자 문자 “a”~ “z”, “A”~ “Z”및 “0”~ ​​”9″는 동일하게 유지됩니다.
  • 특수 문자 “.”, “-“, “*”및 “_”는 동일하게 유지됩니다.
  • 공백 문자 “”는 더하기 부호 “+”로 변환됩니다.
  • 다른 모든 문자는 안전하지 않으며 일부 인코딩 체계를 사용하여 먼저 하나 이상의 바이트로 변환됩니다. 그런 다음 각 바이트는 3 자 문자열 “% xy”로 표시됩니다. 여기서 xy는 바이트의 두 자리 16 진수 표현입니다. 권장되는 인코딩 체계는 UTF-8입니다. 그러나 호환성을 위해 인코딩을 지정하지 않으면 플랫폼의 기본 인코딩이 사용됩니다.

답변

쿼리 매개 변수 인코딩

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;
 }


답변

Hello+World브라우저가 요청에 application/x-www-form-urlencoded대한 양식 데이터 ( )를 인코딩하는 방법 GET이며 이는 URI의 쿼리 부분에 일반적으로 허용되는 양식입니다.

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

이 요청을 Java 서블릿으로 보낸 경우 서블릿은 매개 변수 값을 올바르게 디코딩합니다. 일반적으로 여기에 문제가있는 유일한 시간은 인코딩이 일치하지 않는 경우입니다.

엄밀히 말하면 HTTP 또는 URI 사양에는 쿼리 부분을 사용하여 인코딩해야 할 요구 사항이 없습니다. application/x-www-form-urlencoded 키-값 쌍을 . 쿼리 부분은 웹 서버가 허용하는 형식이어야합니다. 실제로 이것은 문제가되지 않을 것입니다.

URI의 다른 부분 (예 : 경로)에이 인코딩을 사용하는 것은 일반적으로 올바르지 않습니다. 이 경우 RFC 3986에 설명 된 대로 인코딩 체계를 사용해야합니다 .

http://host/Hello%20World

여기에 .


답변

다른 답변은 수동 문자열 대체, 실제로 HTML 형식으로 인코딩하는 URLEncoder , Apache의 버려진 URIUtil 또는 Guava의 UrlEscapers를 사용하는 것 입니다. 마지막은 디코더를 제공하지 않는 한 괜찮습니다.

Apache Commons Lang은 URL 형식 rfc3986 에 따라 인코딩 하고 디코딩 하는 URLCodec을 제공합니다 .

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

이미 Spring을 사용 하고 있다면 UriUtils 클래스 를 사용하도록 선택할 수도 있습니다 .


답변

“+”가 맞습니다. % 20이 정말로 필요하다면, 나중에 Plusses를 교체하십시오.