Java - преобразовать строку в действительный объект URI

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

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

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

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

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

Ответ 1

Вы можете попробовать: 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 может стать довольно грязным...

Ответ 2

У 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"));

Ответ 3

Я собираюсь добавить одно предложение здесь для пользователей 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 и работать с ней без каких-либо специальных знаний о ней.

Ответ 4

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

С библиотекой 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-адресом.

Ответ 5

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

Обратите внимание, что вы не должны использовать эту функцию по всему URL-адресу, вместо этого вы должны использовать это для компонентов... например. просто компонент "a", когда вы создаете 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 " %$&+,/:;[email protected]<>#%".indexOf(ch) >= 0;
}

Ответ 6

Вы можете использовать конструкторы с несколькими аргументами класса 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);

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

Ответ 7

У меня были аналогичные проблемы для одного из моих проектов для создания 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);

Ответ 8

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

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

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

Ответ 9

У блога 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/

Ответ 10

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

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

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

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

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

Ответ 11

В итоге я использовал httpclient-4.3.6:

import org.apache.http.client.utils.URIBuilder;
public static void main (String [] args) {
    URIBuilder uri = new URIBuilder();
    uri.setScheme("http")
    .setHost("www.example.com")
    .setPath("/somepage.php")
    .setParameter("username", "Hello Günter")
    .setParameter("p1", "parameter 1");
    System.out.println(uri.toString());
}

Выход будет:

http://www.example.com/somepage.php?username=Hello+G%C3%BCnter&p1=paramter+1