Como decodificar URL em Java?

323

Em Java, quero converter isso:

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

Para isso:

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

Isto é o que eu tenho até agora:

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){
        }
    }
}

Mas isso não funciona direito. O que são estes %3Ae %2Fformatos de chamada e como faço para convertê-los?

crackerplace
fonte
@ Stephen .. Por que um URL não pode ser String codificada em UTF-8 ..?
Crackerplace
O problema é que, apenas porque o URL pode ser UTF-8, a questão realmente não tem nada a ver com UTF-8. Eu editei a pergunta adequadamente.
Chris Jester-Young
Poderia ser (em teoria), mas a string no seu exemplo não é uma String codificada em UTF-8. É uma sequência ASCII codificada em URL. Portanto, o título é enganoso.
Stephen C
Também é importante notar que todos os caracteres da urlstring são ASCII, e isso também ocorre depois que a string foi decodificada em URL. '%'é um caractere ASCII e %xxrepresenta um caractere ASCII se xxfor menor que (hexadecimal) 80.
Stephen C

Respostas:

634

Isso não tem nada a ver com codificações de caracteres como UTF-8 ou ASCII. A string que você possui é codificada em URL . Esse tipo de codificação é algo completamente diferente da codificação de caracteres.

Tente algo como isto:

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
}

O Java 10 adicionou suporte direto Charsetà API, o que significa que não há necessidade de capturar UnsupportedEncodingException:

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

Observe que uma codificação de caracteres (como UTF-8 ou ASCII) é o que determina o mapeamento de caracteres para bytes brutos. Para uma boa introdução às codificações de caracteres, consulte este artigo .

Jesper
fonte
1
Os métodos URLDecodersão estáticos, assim você não precisa criar uma nova instância.
Laz
2
@Trismegistos Somente a versão em que você não especifica a codificação de caracteres (o segundo parâmetro "UTF-8") é preterida de acordo com a documentação da API do Java 7. Use a versão com dois parâmetros.
Jesper
23
Se estiver usando java 1.7+ você pode usar a versão estática do string "UTF-8": StandardCharsets.UTF_8.name()a partir deste pacote: java.nio.charset.StandardCharsets. Relevante para isso: link
Shahar 30/04
1
Para codificação de caracteres, isto faz um grande artigo também balusc.blogspot.in/2009/05/unicode-how-to-get-characters-right.html
crackerplace
4
Tenha cuidado com isso. Conforme observado aqui: blog.lunatech.com/2009/02/03/… Não se trata de URLs, mas de codificação de formulário HTML.
Michal
52

A string que você tem está na application/x-www-form-urlencodedcodificação.

Use URLDecoder para convertê-lo em Java String.

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

Isso já foi respondido antes (embora essa pergunta tenha sido a primeira!):

"Você deve usar o java.net.URI para fazer isso, pois a classe URLDecoder faz a decodificação x-www-form-urlencoded que está errada (apesar do nome, é para dados do formulário)."

Conforme a documentação da classe URL :

A maneira recomendada de gerenciar a codificação e decodificação de URLs é usar o URI e converter entre essas duas classes usando toURI () e URI.toURL () .

Os URLEncoder e URLDecoder classes também pode ser usado, mas somente para o formulário HTML codificação, que não é o mesmo que o esquema de codificação definido em RFC2396 .

Basicamente:

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

Darei à você:

https://mywebsite/docs/english/site/mybook.do?request_type
Nick Grealy
fonte
6
No Java 1.7, a URLDecoder.decode(String, String)sobrecarga não é preterida. Você deve estar se referindo à URLDecoder.decode(String)sobrecarga sem a codificação. Convém atualizar sua postagem para esclarecimentos.
Aaron
2
Essa resposta é enganosa; essa cotação em bloco não tem nada a ver com a descontinuação. O Javadoc dos estados Método Reprovado, e eu realmente Citação@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
1
getPath () para URIs retorna apenas a parte do caminho do URI, conforme observado acima.
Pelpotronic
2
A menos que eu esteja enganado, o "caminho" é conhecido por ser a parte de um URI após a parte da autoridade (consulte: en.wikipedia.org/wiki/Uniform_Resource_Identifier para definição de caminho) - parece-me o comportamento que estou vendo é o comportamento padrão / correto. Estou usando o java 1.8.0_101 (no Android Studio). Eu ficaria curioso para ver como é chamado "getAuthority ()". Mesmo este artigo / example parece indicar que caminho é só o público / manual aparelhos / parte / de sua URI: quepublishing.com/articles/article.aspx?p=26566&seqNum=3
Pelpotronic
1
@Pelpotronic O código na postagem realmente imprime a saída que mostra (pelo menos para mim). Eu acho que a razão disso é que, devido à codificação da URL, o construtor URI está realmente tratando toda a cadeia ( https%3A%2F...) como apenas o caminho de um URI; não há autoridade ou consulta, etc. Isso pode ser testado chamando os respectivos métodos get no objeto URI. Se você passar o texto decodificado para o construtor URI:, a new URI("https://mywebsite/do.....")chamada getPath()e outros métodos fornecerão os resultados corretos.
Kröw 2/06/19
14

%3Ae %2Fsão caracteres codificados em URL. Use esse código java para convertê-los novamente em :e/

String decoded = java.net.URLDecoder.decode(url, "UTF-8");
Laz
fonte
2
ele não converte% 2C também, é (,)
vuhung3990 6/15
Isso precisa ser envolto em um bloco try / catch .. leia mais sobre exceções verificadas (este) vs desmarcada stackoverflow.com/questions/6115896/...
de Bruno Wolff
5
 try {
        String result = URLDecoder.decode(urlString, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
Hsm
fonte
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
fonte
4
Você poderia elaborar mais sua resposta adicionando um pouco mais de descrição sobre a solução que você fornece?
abarisone
3

Eu uso apache commons

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

O conjunto de caracteres padrão é UTF-8

Classificador
fonte
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")); 

    } 

}

Você pode selecionar seu método com sabedoria :)

rinuthomaz
fonte
0

Usando a classe java.net.URI:

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

Observe que o tratamento de exceções pode ser melhor, mas não é muito relevante para este exemplo.

x7BiT
fonte