it-swarm.dev

Java - Converter String para o objeto URI válido

Eu estou tentando obter um objeto Java.net.URI de um String. A string tem alguns caracteres que precisam ser substituídos por suas seqüências de escape percentuais. Mas quando eu uso URLEncoder para codificar a string com codificação UTF-8, até mesmo o/é substituído por suas seqüências de escape.

Como posso obter uma URL codificada válida de um objeto String?

http://www.google.com?q=a b fornece http% 3A% 2F% 2www.google.com ... enquanto eu quero que a saída seja http://www.google.com?q=a%20b

Alguém pode me dizer como conseguir isso.

Eu estou tentando fazer isso em um aplicativo Android. Então eu tenho acesso a um número limitado de bibliotecas.

69
lostInTransit

Você pode tentar: org.Apache.commons.httpclient.util.URIUtil.encodeQuery em Apache commons-httpclient project

Assim (veja URIUtil ):

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

se tornará:

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

Você pode, claro, fazer você mesmo, mas a análise de URI pode ficar bastante confusa ...

55
Hans Doggen

O Android sempre teve a classe Uri como parte do SDK: http://developer.Android.com/reference/Android/net/Uri.html

Você pode simplesmente fazer algo como:

String requestURL = String.format("http://www.example.com/?a=%s&b=%s", Uri.encode("foo bar"), Uri.encode("100% fubar'd"));
45
bensnider

Vou adicionar uma sugestão aqui destinada a usuários do Android. Você pode fazer isso, o que evita ter que obter bibliotecas externas. Além disso, todas as soluções de caracteres de pesquisa/substituição sugeridas em algumas das respostas acima são perigosas e devem ser evitadas. 

Experimente:

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

Você pode ver que neste URL específico, eu preciso ter esses espaços codificados para que eu possa usá-lo para uma solicitação. 

Isso tira proveito de alguns recursos disponíveis para você nas aulas do Android. Primeiro, a classe URL pode dividir uma URL em seus componentes apropriados, portanto, não há necessidade de fazer qualquer trabalho de busca/substituição de string. Em segundo lugar, essa abordagem tira proveito do recurso de classe URI de escapar adequadamente de componentes quando você constrói um URI por meio de componentes, em vez de uma única cadeia de caracteres.

A beleza dessa abordagem é que você pode pegar qualquer sequência de URL válida e fazer com que ela funcione sem precisar de nenhum conhecimento especial dela. 

33
Craig B

Mesmo que este seja um post antigo com uma resposta já aceita, eu postei minha resposta alternativa porque funciona bem para o presente problema e parece que ninguém mencionou este método.

Com a biblioteca Java.net.URI:

URI uri = URI.create(URLString);

E se você quiser uma string formatada em URL correspondente a ela:

String validURLString = uri.toASCIIString();

Ao contrário de muitos outros métodos (por exemplo, Java.net.URLEncoder), este substitui apenas caracteres não seguros ASCII (como ç, é...).


No exemplo acima, se URLString for o seguinte String:

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

o validURLString resultante será:

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

que é um URL bem formatado.

14
dgiugg

Se você não gosta de bibliotecas, que tal isso?

Observe que você não deve usar essa função em todo o URL, em vez disso, deve usar isso nos componentes ... por exemplo, apenas o componente "a b", conforme você constrói a URL - caso contrário, o computador não saberá quais caracteres devem ter um significado especial e quais devem ter um significado literal.

/** 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;
}
9
Tim Cooper

Você pode usar os construtores multi-argumentos da classe URI. Do URI javadoc:

Os construtores multi-argumentos citam caracteres inválidos, conforme exigido pelos componentes em que aparecem. O caractere de porcentagem ('%') é sempre citado por esses construtores. Quaisquer outros caracteres são preservados.

Então, se você usar

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

Então você obtém http:www.google.com?q=a%20b que não está certo, mas é um pouco mais próximo.

Se você souber que sua string não terá fragmentos de URL (por exemplo, http://example.com/page#anchor ), poderá usar o código a seguir para conseguir o que deseja:

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

Por segurança, você deve escanear a string para caracteres #, mas isso deve começar.

4
Jason Day

Eu tive problemas semelhantes para um dos meus projetos para criar um objeto URI a partir de uma string. Também não consegui encontrar nenhuma solução limpa. Aqui está o que eu criei:

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;
}

Você pode usar o seguinte construtor de URI para especificar uma porta, se necessário:

URI uri = new URI(scheme, userInfo, Host, port, path, query, fragment);
4
Hervé Donner

Bem, eu tentei usar 

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

Eu espero que isso seja o que você estava realmente procurando?

3
Amol Ghotankar

Ou talvez você possa usar essa classe:

http://developer.Android.com/reference/Java/net/URLEncoder.html

Que está presente no Android desde o nível 1 da API.

Irritantemente no entanto, trata espaços especialmente (substituindo-os por + em vez de% 20). Para contornar isso, simplesmente usamos este fragmento:

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

1
MrCranky

O blog do Java.net teve uma aula no outro dia que poderia ter feito o que você quer (mas está no ar agora, então não posso verificar). 

Este código aqui provavelmente poderia ser modificado para fazer o que você quer:

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

Aqui está o que eu estava pensando em Java.net: https://urlencodedquerystring.dev.Java.net/

1
TofuBeer

Acabei usando o 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());
}

A saída será:

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