¿Cómo hacer la decodificación de URL en Java?

323

En Java, quiero convertir esto:

https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do%3Frequest_type

A esto:

https://mywebsite/docs/english/site/mybook.do&request_type

Esto es lo que tengo hasta ahora:

class StringUTF 
{
    public static void main(String[] args) 
    {
        try{
            String url = 
               "https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do" +
               "%3Frequest_type%3D%26type%3Dprivate";

            System.out.println(url+"Hello World!------->" +
                new String(url.getBytes("UTF-8"),"ASCII"));
        }
        catch(Exception E){
        }
    }
}

Pero no funciona bien. ¿Cómo se llaman estos %3Ay %2Fformatos y cómo los convierto?

crackerplace
fuente
@Stephen .. ¿Por qué una url no puede ser una cadena codificada en UTF-8?
crackerplace
El problema es que solo porque la URL puede ser UTF-8, la pregunta realmente no tiene nada que ver con UTF-8. He editado la pregunta adecuadamente.
Chris Jester-Young
Podría ser (en teoría), pero la cadena en su ejemplo no es una cadena codificada en UTF-8. Es una cadena ASCII codificada en URL. Por lo tanto, el título es engañoso.
Stephen C
También vale la pena señalar que todos los caracteres en la urlcadena son ASCII, y esto también es cierto después de que la cadena ha sido decodificada por URL. '%'es un carácter ASCII y %xxrepresenta un carácter ASCII si xxes menor que (hexadecimal) 80.
Stephen C

Respuestas:

634

Esto no tiene nada que ver con codificaciones de caracteres como UTF-8 o ASCII. La cadena que tiene allí está codificada en URL . Este tipo de codificación es algo completamente diferente a la codificación de caracteres.

Intenta algo como esto:

try {
    String result = java.net.URLDecoder.decode(url, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
    // not going to happen - value came from JDK's own StandardCharsets
}

Java 10 agregó soporte directo para Charsetla API, lo que significa que no hay necesidad de detectar UnsupportedEncodingException:

String result = java.net.URLDecoder.decode(url, StandardCharsets.UTF_8);

Tenga en cuenta que una codificación de caracteres (como UTF-8 o ASCII) es lo que determina la asignación de caracteres a bytes sin formato. Para una buena introducción a las codificaciones de caracteres, vea este artículo .

Jesper
fuente
1
Los métodos URLDecoderson estáticos, por lo que no tiene que crear una nueva instancia.
laz
2
@Trismegistos Solo la versión donde no especifica la codificación de caracteres (el segundo parámetro "UTF-8") está en desuso según la documentación de la API de Java 7. Use la versión con dos parámetros.
Jesper
23
Si se utiliza Java 1.7+ puede utilizar la versión estática de la cadena "UTF-8": StandardCharsets.UTF_8.name()de este paquete: java.nio.charset.StandardCharsets. Relevante para esto: enlace
Shahar
1
Para la codificación de caracteres, esto también hace un gran artículo balusc.blogspot.in/2009/05/unicode-how-to-get-characters-right.html
crackerplace
44
Ten cuidado con esto. Como se señaló aquí: blog.lunatech.com/2009/02/03/… Esto no se trata de URL, sino de codificación de formulario HTML.
Michal
52

La cadena que tienes está en la application/x-www-form-urlencodedcodificación.

Use URLDecoder para convertirlo a Java String.

URLDecoder.decode( url, "UTF-8" );
Alexander Pogrebnyak
fuente
47

Esto ha sido respondido antes (¡aunque esta pregunta fue la primera!):

"Debería usar java.net.URI para hacer esto, ya que la clase URLDecoder realiza una decodificación x-www-form-urlencoded que es incorrecta (a pesar del nombre, es para datos de formulario)".

Como dice la documentación de la clase de URL :

La forma recomendada de administrar la codificación y decodificación de URL es usar URI y convertir entre estas dos clases usando toURI () y URI.toURL () .

Las clases URLEncoder y URLDecoder también se pueden usar, pero solo para la codificación de formularios HTML, que no es lo mismo que el esquema de codificación definido en RFC2396 .

Básicamente:

String url = "https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do%3Frequest_type";
System.out.println(new java.net.URI(url).getPath());

Te regalaré:

https://mywebsite/docs/english/site/mybook.do?request_type
Nick Grealy
fuente
66
En Java 1.7, la URLDecoder.decode(String, String)sobrecarga no está en desuso. Debe referirse a la URLDecoder.decode(String)sobrecarga sin la codificación. Es posible que desee actualizar su publicación para aclararla.
Aaron
2
Esta respuesta es engañosa; esa cita en bloque no tiene nada que ver con la desaprobación. El Javadoc del método obsoleto dice, y en realidad cito@deprecated The resulting string may vary depending on the platform's default encoding. Instead, use the decode(String,String) method to specify the encoding.
Emerson Farrugia el
1
getPath () para URI solo devuelve la parte de ruta del URI, como se indicó anteriormente.
Pelpotronic
2
A menos que me equivoque, se sabe que la "ruta" es esa parte de un URI después de la parte de autoridad (ver: en.wikipedia.org/wiki/Uniform_Resource_Identifier para la definición de ruta) - me parece el comportamiento que estoy viendo Es el comportamiento estándar / correcto. Estoy usando java 1.8.0_101 (en Android Studio). Tengo curiosidad por ver cómo se obtiene como se llama "getAuthority ()". Incluso este artículo / ejemplo parece indicar que la ruta es solo la parte / public / manual / appliances de su URI: quepublishing.com/articles/article.aspx?p=26566&seqNum=3
Pelpotronic
1
@Pelpotronic El código en la publicación en realidad imprime el resultado que muestra (al menos para mí). Creo que la razón de esto es que, debido a la codificación de URL, el constructor de URI en realidad está tratando toda la cadena, ( https%3A%2F...), como solo la ruta de un URI; no hay autoridad, consulta, etc. Esto se puede probar llamando a los respectivos métodos get en el objeto URI. Si pasa el texto decodificado al constructor de URI:, new URI("https://mywebsite/do.....")entonces llamar getPath()y otros métodos darán resultados correctos.
Kröw
14

%3Ay %2Fson caracteres codificados en URL. Use este código Java para convertirlos nuevamente en :y/

String decoded = java.net.URLDecoder.decode(url, "UTF-8");
perezoso
fuente
2
tampoco convierte% 2C, es (,)
vuhung3990
esto debe estar envuelto en un bloque try / catch ... lea más sobre las excepciones marcadas (esta) vs stackoverflow.com/questions/6115896/…
Bruno Wolff
5
 try {
        String result = URLDecoder.decode(urlString, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
Hsm
fuente
5
public String decodeString(String URL)
    {

    String urlString="";
    try {
        urlString = URLDecoder.decode(URL,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block

        }

        return urlString;

    }
Ronak Poriya
fuente
44
¿Podría por favor elaborar más su respuesta agregando un poco más de descripción sobre la solución que proporciona?
abarisone
3

Yo uso apache commons

String decodedUrl = new URLCodec().decode(url);

El juego de caracteres predeterminado es UTF-8

Clasificador
fuente
2
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;

public class URLDecoding { 

    String decoded = "";

    public String decodeMethod(String url) throws UnsupportedEncodingException
    {
        decoded = java.net.URLDecoder.decode(url, "UTF-8"); 
        return  decoded;
//"You should use java.net.URI to do this, as the URLDecoder class does x-www-form-urlencoded decoding which is wrong (despite the name, it's for form data)."
    }

    public String getPathMethod(String url) throws URISyntaxException 
    {
        decoded = new java.net.URI(url).getPath();  
        return  decoded; 
    }

    public static void main(String[] args) throws UnsupportedEncodingException, URISyntaxException 
    {
        System.out.println(" Here is your Decoded url with decode method : "+ new URLDecoding().decodeMethod("https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do%3Frequest_type")); 
        System.out.println("Here is your Decoded url with getPath method : "+ new URLDecoding().getPathMethod("https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do%3Frequest")); 

    } 

}

Puede seleccionar su método sabiamente :)

rinuthomaz
fuente
0

Usando la clase java.net.URI:

public String getDecodedURL(String encodedUrl) {
    try {
        URI uri = new URI(encodedUrl);
        return uri.getScheme() + ":" + uri.getSchemeSpecificPart();
    } catch (Exception e) {
        return "";
    }
}

Tenga en cuenta que el manejo de excepciones puede ser mejor, pero no es muy relevante para este ejemplo.

x7BiT
fuente