Java - конвертировать строку в действительный объект URI - PullRequest
70 голосов
/ 21 февраля 2009

Я пытаюсь получить объект java.net.URI из String. В строке есть несколько символов, которые необходимо заменить на их escape-последовательности в процентах. Но когда я использую URLEncoder для кодирования строки с кодировкой UTF-8, даже / заменяются их escape-последовательностями.

Как я могу получить действительный закодированный URL из объекта String?

http://www.google.com? Q = a b дает http% 3A% 2F% 2www.google.com ... , тогда как я хочу, чтобы вывод быть http://www.google.com? q =% 20b

Может кто-нибудь подскажите, пожалуйста, как этого добиться.

Я пытаюсь сделать это в приложении для Android. Так что у меня есть доступ к ограниченному количеству библиотек.

Ответы [ 11 ]

56 голосов
/ 21 февраля 2009

Вы можете попробовать: org.apache.commons.httpclient.util.URIUtil.encodeQuery в Apache commons-httpclient project

Вот так (см. URIUtil ):

URIUtil.encodeQuery("http://www.google.com?q=a b")

станет:

http://www.google.com?q=a%20b

Конечно, вы можете сделать это самостоятельно, но разбор URI может стать довольно грязным ...

45 голосов
/ 07 апреля 2011

У Android всегда был класс Uri как часть SDK: http://developer.android.com/reference/android/net/Uri.html

Вы можете просто сделать что-то вроде:

String requestURL = String.format("http://www.example.com/?a=%s&b=%s", Uri.encode("foo bar"), Uri.encode("100% fubar'd"));
33 голосов
/ 22 января 2012

Я собираюсь добавить одно предложение, предназначенное для пользователей Android. Вы можете сделать это, чтобы избежать необходимости получать какие-либо внешние библиотеки. Кроме того, все решения поиска / замены символов, предложенные в некоторых из приведенных выше ответов, опасны и их следует избегать.

Дайте попробовать:

String urlStr = "http://abc.dev.domain.com/0007AC/ads/800x480 15sec h.264.mp4";
URL url = new URL(urlStr);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
url = uri.toURL();

Вы видите, что в этом конкретном URL мне нужно закодировать эти пробелы, чтобы я мог использовать его для запроса.

Для этого используются несколько функций, доступных вам в классах Android. Во-первых, класс URL может разбить URL-адрес на соответствующие компоненты, поэтому вам не нужно выполнять поиск / замену строк. Во-вторых, этот подход использует преимущество класса URI для правильного экранирования компонентов, когда вы создаете URI через компоненты, а не из одной строки.

Прелесть этого подхода в том, что вы можете взять любую действительную строку URL-адреса и заставить ее работать, не требуя каких-либо специальных знаний о себе.

14 голосов
/ 06 августа 2014

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

С библиотекой java.net.URI:

URI uri = URI.create(URLString);

И если вам нужна соответствующая ей строка в формате URL:

String validURLString = uri.toASCIIString();

В отличие от многих других методов (например, java.net.URLEncoder) этот метод заменяет только небезопасные символы ASCII (например, ç, é ...).


В приведенном выше примере, если URLString является следующим String:

"http://www.domain.com/façon+word"

В результате validURLString будет:

"http://www.domain.com/fa%C3%A7on+word"

, который является хорошо отформатированным URL.

9 голосов
/ 26 июля 2010

Если вам не нравятся библиотеки, как насчет этого?

Обратите внимание, что вы не должны использовать эту функцию на всем URL, вместо этого вы должны использовать это на компонентах ... например. просто компонент «b», когда вы создаете URL-адрес, иначе компьютер не будет знать, какие символы должны иметь особое значение, а какие - буквальное.

/** Converts a string into something you can safely insert into a URL. */
public static String encodeURIcomponent(String s)
{
    StringBuilder o = new StringBuilder();
    for (char ch : s.toCharArray()) {
        if (isUnsafe(ch)) {
            o.append('%');
            o.append(toHex(ch / 16));
            o.append(toHex(ch % 16));
        }
        else o.append(ch);
    }
    return o.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;
}
4 голосов
/ 20 января 2012

У меня были похожие проблемы для одного из моих проектов по созданию объекта URI из строки. Я не мог найти ни одного чистого решения. Вот что я придумал:

public static URI encodeURL(String url) throws MalformedURLException, URISyntaxException  
{
    URI uriFormatted = null; 

    URL urlLink = new URL(url);
    uriFormatted = new URI("http", urlLink.getHost(), urlLink.getPath(), urlLink.getQuery(), urlLink.getRef());

    return uriFormatted;
}

Вместо этого можно использовать следующий конструктор URI, чтобы указать порт при необходимости:

URI uri = new URI(scheme, userInfo, host, port, path, query, fragment);
4 голосов
/ 21 февраля 2009

Вы можете использовать много аргументные конструкторы класса URI. Из URI Javadoc:

Конструкторы с несколькими аргументами заключают в кавычки недопустимые символы, как того требуют компоненты, в которых они появляются. Символ процента ('%') всегда указывается этими конструкторами. Любые другие символы сохраняются.

Так что, если вы используете

URI uri = new URI("http", "www.google.com?q=a b");

Тогда вы получите http:www.google.com?q=a%20b, что не совсем правильно, но это немного ближе.

Если вы знаете, что в вашей строке не будет фрагментов URL (например, http://example.com/page#anchor),), вы можете использовать следующий код, чтобы получить то, что вы хотите:

String s = "http://www.google.com?q=a b";
String[] parts = s.split(":",2);
URI uri = new URI(parts[0], parts[1], null);

На всякий случай вам следует отсканировать строку на наличие # символов, но это должно помочь вам начать работу.

3 голосов
/ 12 июля 2012

Ну, я пытался использовать

String converted = URLDecoder.decode("toconvert","UTF-8");

Надеюсь, это то, что вы на самом деле искали?

1 голос
/ 12 января 2011

Или, возможно, вы могли бы использовать этот класс:

http://developer.android.com/reference/java/net/URLEncoder.html

Что присутствует в Android начиная с уровня API 1.

Но, к сожалению, он обрабатывает пробелы специально (заменяя их на + вместо% 20). Чтобы обойти это, мы просто используем этот фрагмент:

URLEncoder.encode(value, "UTF-8").replace("+", "%20");

1 голос
/ 21 февраля 2009

На днях в блоге java.net был класс, который мог бы делать то, что вы хотите (но сейчас он недоступен, поэтому я не могу проверить).

Этот код, вероятно, можно изменить, чтобы сделать то, что вы хотите:

http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/uri/UriBuilder.java

Вот тот, о котором я думал из java.net: https://urlencodedquerystring.dev.java.net/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...