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



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



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



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



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



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

863   11  

11 ответов:

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

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

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

будет:

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

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

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

Я собираюсь добавить одно предложение здесь, направленное на пользователей 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-адресе мне нужно закодировать эти пробелы, чтобы я мог использовать его для запроса.

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

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

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

с библиотекой 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.

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

обратите внимание, что вы не должны использовать эту функцию на весь URL, вместо этого вы должны использовать это на компонентах...например, просто компонент "a 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;
}

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

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

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

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

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

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

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/

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

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

который присутствует в Android с уровня API 1.

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

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

Я в конечном итоге с помощью 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

Comments

    Ничего не найдено.