2009-02-21 31 views
66

Estoy tratando de obtener un objeto java.net.URI desde String. La cadena tiene algunos caracteres que deberán ser reemplazados por sus secuencias de porcentaje de escape. Pero cuando uso URLEncoder para codificar el String con codificación UTF-8, incluso/se reemplazan con sus secuencias de escape.Java - Convertir cadena en objeto URI válido

¿Cómo puedo obtener una URL codificada válida de un objeto String?

http://www.google.com?q=a b da http% 3A% 2F% 2www.google.com ... mientras que yo quiero que la salida sea http://www.google.com?q=a%20b

Puede alguien por favor dígame cómo lograr esto.

Estoy tratando de hacer esto en una aplicación de Android. Así que tengo acceso a un número limitado de bibliotecas.

Respuesta

55

Usted puede tratar de: org.apache.commons.httpclient.util.URIUtil.encodeQuery en Apache commons-httpclient proyecto

gusta esta (ver URIUtil):

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

se convertirá en:

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

Por supuesto, puedes hacerlo por sí solo, pero URI el análisis puede ser bastante complicado ...

+0

Gracias Hans. Estoy tratando de hacer esto en una aplicación de Android. Así que tengo acceso a un número limitado de bibliotecas. ¿Tiene alguna otra sugerencia? Gracias de nuevo – lostInTransit

+2

Quizás puedas echar un vistazo a la fuente de la clase URIUtil (después de todo es de código abierto). Supongo que es posible extraer el código necesario de esa clase. –

+6

El proyecto puntual (Apache commons-httpclient) "ahora es el final de la vida útil". Ha sido reemplazado en parte por [HttpComponents-httpclient] (http://hc.apache.org/httpcomponents-client-ga) pero no pude encontrar un método equivalente en la nueva API. – dgiugg

4

Puede utilice los constructores de argumentos múltiples de la clase URI. Desde URI javadoc:

Los constructores de argumentos múltiples citan caracteres ilegales según lo exigen los componentes en los que aparecen. El carácter de porcentaje ('%') siempre es citado por estos constructores. Cualquier otro personaje se conserva.

tanto, si utiliza

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

A continuación presentamos lo mejor http:www.google.com?q=a%20b que no está del todo bien, pero es un poco más cerca.

Si usted sabe que su cadena no tendrá fragmentos de URL (por ejemplo http://example.com/page#anchor), entonces usted puede utilizar el código siguiente para obtener lo que desea:

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

Para estar seguro, usted debe escanear la cadena de # caracteres, pero esto debería comenzar.

9

Si no te gustan las bibliotecas, ¿qué tal esto?

Tenga en cuenta que no debe usar esta función en toda la URL, en su lugar debe usar esto en los componentes ... por ejemplo. solo el componente "a b", a medida que construye la URL; de lo contrario, la computadora no sabrá qué caracteres se supone que tienen un significado especial y cuáles se supone que tienen un 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; 
} 
+0

Esto no funciona (al menos en algunos casos). P.ej. el carácter 'Š' está codificado como '% M1', pero debe codificarse como '% C5% A0'. – mindas

+0

Esto tampoco funciona con caracteres como tab. Sugeriría que esto se modifique para que no sea seguro si no coincide [A-Za-z0-9 _-. ~]. Consulte http://en.wikipedia.org/wiki/Percent-encoding – Gray

1

O tal vez usted podría utilizar esta clase:

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

que está presente en Android desde el nivel de la API 1.

embargo Irritantemente, que trata los espacios especialmente (reemplazándolos con + en lugar de% 20). Para evitar esto simplemente utilizar este fragmento:

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

+1

Esto daría http://www.google.com?q=a+b no http://www.google.com?q=a% 20b como se desee. – rpcutts

+0

Ah, sí, me encontré unas semanas después. Se modificará la respuesta para reflejar lo que realmente terminamos usando – MrCranky

+1

Este método ya está depreciado, los usuarios deben especificar un método para la codificación, consulte: http://docs.oracle.com/javase/1.4.2/docs/api/java/net /URLEncoder.html – Aidanc

45

Android siempre ha tenido la clase Uri como parte del SDK: http://developer.android.com/reference/android/net/Uri.html

Simplemente puede hacer algo como:

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

excelente sugerencia - gracias –

+4

¡Muchas gracias! ¡Es ridículo cuánto tiempo lleva a veces encontrar una función Java simple! – Abdo

+1

Desafortunadamente, el método encode() es una mierda cuando se trata de codificar barras diagonales ("/"). Acabo de utilizar un viejo String.replace() para hacer el trabajo. Eso fue muy cojo ... searchQuery.replace ("/", "% 2f"); –

4

Tuve problemas similares para uno de mis proyectos para crear un objeto URI a partir de una cadena. No pude encontrar ninguna solución limpia tampoco. Esto es lo que ocurrió:

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

Se puede utilizar el siguiente constructor URI en lugar de especificar un puerto si es necesario:

URI uri = new URI(scheme, userInfo, host, port, path, query, fragment); 
+0

No se puede convertir un signo de interrogación (lo probé con la URL: 'http://www.google.com/ ¿Te gusta el correo no deseado?'y se ocupó de los espacios, pero no del signo de interrogación al final) – kentcdodds

+0

@kentcdodds es porque el signo de interrogación es legal en este caso. Estoy seguro de que si agrega otro después, se convertiría en – Sebas

33

Voy a añadir una sugerencia aquí dirigida a los usuarios de Android. Puede hacer esto, lo que evita tener que obtener bibliotecas externas. Además, todas las soluciones de búsqueda/reemplazo de caracteres sugeridas en algunas de las respuestas anteriores son peligrosas y deben evitarse.

seguirlo:

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

Se puede ver que en esta URL en particular, necesito tener esos espacios codificados de modo que pueda usarlo para una solicitud.

Esto aprovecha un par de funciones disponibles para usted en las clases de Android. En primer lugar, la clase de URL puede dividir una url en sus componentes adecuados, por lo que no es necesario que realice ningún trabajo de búsqueda/reemplazo de cadenas. En segundo lugar, este enfoque aprovecha la característica de clase URI de escapes adecuados de componentes cuando se construye un URI a través de componentes en lugar de a partir de una sola cadena.

La belleza de este enfoque es que puede tomar cualquier cadena de URL válida y hacer que funcione sin necesidad de ningún conocimiento especial de la misma.

3

Bueno he intentado usar

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

espero que esto es lo que realmente busca?

+0

Gracias, amigo. ¡Eso funciono! –

+0

Esta es la respuesta que estaba buscando y no requiere dependencia de las bibliotecas externas. –

+1

No, esta es una respuesta incorrecta. 'URLDecoder.decode (" para convertir "," UTF-8 ")' devuelve "para convertir" y 'URLDecoder.decode (" para% 20convert "," UTF-8 ")' devuelve "para convertir". Entonces esto hace lo contrario de lo que la pregunta está haciendo. –

13

Aunque esta es una publicación anterior con una respuesta ya aceptada, publico mi respuesta alternativa porque funciona bien para el presente número y parece que nadie mencionó este método.

Con la biblioteca java.net.URI:

URI uri = URI.create(URLString); 

Y si quieres una cadena con formato URL correspondiente a la misma:

String validURLString = uri.toASCIIString(); 

A diferencia de muchos otros métodos (por ejemplo, java.net. URLEncoder) este reemplaza solo caracteres ASCII inseguros (como ç, é ...).


En el ejemplo anterior, si URLString es la siguiente String:

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

la validURLString resultante será:

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

que es un URL bien formateado.

+1

tu respuesta fue la que estaba buscando, no pude extraer el parámetro por varias razones y este es el único método que realmente funcionó. – Ramin

+0

Y todo el mundo debería echar un vistazo a la documentación cuando se trata de excepciones http://developer.android.com/reference/java/net/URI.html#create(java.lang.String) –

+0

Esto no parece convertir ¿citas? es decir, " – behelit

0

Terminé usando el 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()); 
} 

de salida será:

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