Как сделать декодирование URL в Java?

323

В Java я хочу преобразовать это:

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

К этому:

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

Это то, что я до сих пор:

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

Но это не работает правильно. Что это %3Aи %2Fформаты называется и как конвертировать их?

crackerplace
источник
@Stephen .. Почему URL не может быть строкой в ​​кодировке UTF-8 ..?
взломщик
Проблема в том, что только потому, что URL-адрес может быть UTF-8, вопрос действительно не имеет ничего общего с UTF-8. Я отредактировал вопрос соответствующим образом.
Крис Шутер-Янг
Это может быть (теоретически), но строка в вашем примере не является строкой в ​​кодировке UTF-8. Это строка ASCII в кодировке URL. Следовательно, название вводит в заблуждение.
Стивен С
Также стоит отметить, что все символы в urlстроке являются ASCII, и это также верно после того, как строка была декодирована URL. '%'является символом ASCII и %xxпредставляет символ ASCII, если xxон меньше (шестнадцатеричный) 80.
Стивен С

Ответы:

634

Это не имеет ничего общего с кодировками символов, такими как UTF-8 или ASCII. Строка, которая у вас есть, имеет URL в кодировке . Этот вид кодирования отличается от кодировки символов.

Попробуйте что-то вроде этого:

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 добавила прямую поддержку CharsetAPI, что означает, что нет необходимости перехватывать UnsupportedEncodingException:

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

Обратите внимание, что кодировка символов (например, UTF-8 или ASCII) - это то, что определяет отображение символов в необработанные байты. Для хорошего введения в кодировки символов, смотрите эту статью .

Jesper
источник
1
Методы on URLDecoderявляются статическими, поэтому вам не нужно создавать его новый экземпляр.
Лаз
2
@Trismegistos Только версия, в которой вы не указываете кодировку символов (второй параметр "UTF-8"), не рекомендуется в соответствии с документацией по API Java 7. Используйте версию с двумя параметрами.
Джеспер
23
При использовании Java 1.7+ вы можете использовать версию статической строки «UTF-8»: StandardCharsets.UTF_8.name()из этого пакета: java.nio.charset.StandardCharsets. Относится к этому: ссылка
Шахар
1
Для кодировки символов это тоже отличная статья balusc.blogspot.in/2009/05/unicode-how-to-get-characters-right.html
crackerplace
4
Будьте осторожны с этим. Как отмечено здесь: blog.lunatech.com/2009/02/03/… Это не о URL, а о кодировании HTML-форм.
Михал
52

У вас есть строка в application/x-www-form-urlencodedкодировке.

Используйте URLDecoder для преобразования его в строку Java.

URLDecoder.decode( url, "UTF-8" );
Александр Погребняк
источник
47

Это было отвечено , прежде чем (хотя этот вопрос был первым!):

«Для этого вам следует использовать java.net.URI, поскольку класс URLDecoder выполняет декодирование в формате x-www-form-urlencoded, что неверно (несмотря на название, это для данных формы)».

Как указано в документации класса URL :

Рекомендуемый способ управления кодированием и декодированием URL-адресов заключается в использовании URI и преобразовании между этими двумя классами с помощью toURI () и URI.toURL () .

В URLEncoder и раскодирования URL- адреса классы также могут быть использованы, но только для вида кодирования HTML, который не является таким же , как схема кодирования , определенной в RFC2396 .

В принципе:

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

дам тебе:

https://mywebsite/docs/english/site/mybook.do?request_type
Ник Грили
источник
6
В Java 1.7 URLDecoder.decode(String, String)перегрузка не считается устаревшей. Вы должны ссылаться на URLDecoder.decode(String)перегрузку без кодировки. Вы можете обновить свой пост для уточнения.
Аарон
2
Этот ответ вводит в заблуждение; эта блочная цитата не имеет ничего общего с устареванием. В Javadoc об устаревшем методе говорится, и я на самом деле цитирую@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 () для URI возвращает только часть пути URI, как отмечено выше.
Пелпотроник
2
Если я не ошибаюсь, «путь», как известно, является той частью URI после авторитетной части (см. Определение пути путем (см .: en.wikipedia.org/wiki/Uniform_Resource_Identifier ) - мне кажется поведение, которое я вижу это стандартное / правильное поведение. Я использую Java 1.8.0_101 (на Android Studio). Мне было бы любопытно увидеть, что вы получаете, как называется "getAuthority ()". Даже эта статья / пример, кажется, указывает, что путь является только частью / public / manual / devices
Pelpotronic
1
@Pelpotronic Код в посте на самом деле печатает вывод, который он показывает (по крайней мере, для меня). Я думаю, что причина этого заключается в том, что из-за кодировки URL конструктор URI фактически обрабатывает всю строку ( https%3A%2F...) как просто путь URI; нет полномочий или запросов и т. д. Это можно проверить, вызвав соответствующие методы get для объекта URI. Если вы передадите декодированный текст в конструктор URI:, new URI("https://mywebsite/do.....")то вызов getPath()и другие методы дадут правильные результаты.
Kröw
14

%3Aи %2Fявляются URL-кодированными символами. Используйте этот код Java, чтобы преобразовать их обратно в :и/

String decoded = java.net.URLDecoder.decode(url, "UTF-8");
Лаз
источник
2
это не конвертирует% 2C тоже, это (,)
vuhung3990
это должно быть заключено в блок try / catch .. узнайте больше о проверенных исключениях (этот) против непроверенного 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
источник
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;

    }
Ронак Пория
источник
4
Не могли бы вы более подробно изложить свой ответ, добавив немного больше описания предлагаемого вами решения?
abarisone
3

Я использую Apache Commons

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

Кодировка по умолчанию UTF-8

сортировщик
источник
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")); 

    } 

}

Вы можете выбрать свой метод с умом :)

rinuthomaz
источник
0

Используя класс java.net.URI:

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

Обратите внимание, что обработка исключений может быть лучше, но это не очень важно для этого примера.

x7BiT
источник