Codificación de la URL de Java de los parámetros de la cadena de consulta

Digamos que tengo una URL

http://example.com/query?q=

y tengo una consulta introducida por el usuario como:

palabra aleatoria £500 banco $

Quiero que el resultado sea una URL correctamente codificada:

http://example.com/query?q=random%20word%20%A3500%20bank%20%24

¿Cuál es la mejor manera de conseguirlo? He probado con URLEncoder y con la creación de objetos URI/URL, pero ninguno de ellos me sale del todo bien.

Solución

URLEncoder debería ser el camino a seguir. Sólo tienes que tener en cuenta que debes codificar sólo el nombre y/o el valor del parámetro de la cadena de consulta, no toda la URL, y por supuesto no el carácter separador del parámetro de la cadena de consulta & ni el carácter separador del nombre-valor del parámetro =.

String q = "random word £500 bank $";
String url = "http://example.com/query?q=" + URLEncoder.encode(q, "UTF-8");

Tenga en cuenta que los espacios en los parámetros de consulta se representan con +, no con %20, que es legítimamente válido. El %20 suele utilizarse para representar espacios en la propia URI (la parte anterior al carácter separador de la cadena de consulta URI ?), no en la cadena de consulta (la parte posterior a ?).

Tenga en cuenta también que hay dos métodos encode(). Uno sin el argumento charset y otro con él. El que no tiene el argumento charset está obsoleto. No lo utilice nunca y especifique siempre el argumento charset. El javadoc incluso recomienda explícitamente el uso de la codificación UTF-8, tal y como mandan el RFC3986 y el W3C.

Todos los demás caracteres son inseguros y se convierten primero en uno o más bytes utilizando algún esquema de codificación. A continuación, cada byte se representa mediante la cadena de 3 caracteres "%xy", donde xy es la representación hexadecimal de dos dígitos del byte. El esquema de codificación recomendado es UTF-8. Sin embargo, por razones de compatibilidad, si no se especifica una codificación, se utiliza la codificación por defecto de la plataforma.

Ver también:

Comentarios (11)

Yo no usaría URLEncoder. Además de tener un nombre incorrecto (URLEncoder no tiene nada que ver con las URLs), es ineficiente (utiliza un StringBuffer en lugar de Builder y hace un par de cosas más que son lentas) y es demasiado fácil de estropear.

En su lugar yo usaría URIBuilder o Spring's org.springframework.web.util.UriUtils.encodeQuery o Commons Apache HttpClient. La razón es que tiene que escapar el nombre de los parámetros de consulta (es decir, BalusC's respuesta q) de manera diferente que el valor del parámetro.

La única desventaja de lo anterior (que descubrí dolorosamente) es que URL's no son un verdadero subconjunto de URI's.

Código de ejemplo:

import org.apache.http.client.utils.URIBuilder;

URIBuilder ub = new URIBuilder("http://example.com/query");
ub.addParameter("q", "random word £500 bank \$");
String url = ub.toString();

// Result: http://example.com/query?q=random+word+%C2%A3500+bank+%24

Como sólo estoy enlazando a otras respuestas, he marcado esto como un wiki de la comunidad. Siéntete libre de editarlo.

Comentarios (9)