2009-02-21 20 views
66

Sto cercando di ottenere un oggetto java.net.URI da un String. La stringa ha alcuni caratteri che dovranno essere sostituiti dalle loro sequenze di escape percentuali. Ma quando uso URLEncoder per codificare String con la codifica UTF-8, anche i/sono sostituiti con le loro sequenze di escape.Java - Converti stringa in oggetto URI valido

Come posso ottenere un URL codificato valido da un oggetto String?

http://www.google.com?q=a bhttp% 3A% 2F% 2www.google.com ... mentre io voglio l'uscita sia http://www.google.com?q=a%20b

qualcuno può dirmi come raggiungere questo obiettivo.

Sto provando a farlo in un'app Android. Quindi ho accesso a un numero limitato di librerie.

risposta

55

Si potrebbe provare: org.apache.commons.httpclient.util.URIUtil.encodeQuery in Apache commons-httpclient progetto

Ti piace questa (vedi URIUtil):

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

diventerà:

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

Ovviamente si può fare da soli, ma URI l'analisi può diventare piuttosto complicata ...

+0

Grazie Hans. Sto cercando di farlo in un'app Android. Quindi ho accesso a un numero limitato di librerie. Avete altri suggerimenti? Grazie ancora – lostInTransit

+2

Forse potresti dare un'occhiata all'origine della classe URIUtil (dopo tutto è open source). Suppongo che sia possibile estrarre il codice necessario da quella classe. –

+6

Il progetto a punta (Apache commons-httpclient) "è ora fine della vita". È stato in parte sostituito da [HttpComponents-httpclient] (http://hc.apache.org/httpcomponents-client-ga) ma non sono riuscito a trovare un metodo equivalente nella nuova API. – dgiugg

4

È possibile utilizzare i costruttori multi-argomento della classe URI. Da URI javadoc:

I costruttori a più argomenti citano caratteri non consentiti come richiesto dai componenti in cui compaiono. Il carattere percentuale ('%') è sempre citato da questi costruttori. Tutti gli altri caratteri sono conservati.

quindi se si utilizza

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

poi si arriva http:www.google.com?q=a%20b, che non è giusto, ma è un po 'più vicino.

Se si sa che la stringa non avrà frammenti di URL (ad esempio http://example.com/page#anchor), quindi è possibile utilizzare il seguente codice per ottenere quello che vuoi:

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

Per essere sicuri, si dovrebbe eseguire la scansione del stringa per # caratteri, ma questo dovrebbe iniziare.

9

Se non ti piacciono le biblioteche, che ne dici di questo?

Si noti che non si dovrebbe usare questa funzione sull'intero URL, ma si dovrebbe usare questo sui componenti ... ad es. solo il componente "a b", mentre costruisci l'URL, altrimenti il ​​computer non saprà quali caratteri dovrebbero avere un significato speciale e quali dovrebbero avere un significato letterale.

/** 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

Questo non funziona (almeno in alcuni casi). Per esempio. il carattere 'Š' è codificato come '% M1', ma dovrebbe essere codificato come '% C5% A0'. – mindas

+0

Anche questo non funziona con caratteri come tab. Suggerirei che questo non sia sicuro se non corrisponde a [A-Za-z0-9 _-. ~]. Vedi http://en.wikipedia.org/wiki/Percent-encoding – Gray

1

O forse si potrebbe usare questa classe:

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

che è presente in Android dal livello di API 1.

Fastidiosamente tuttavia, si tratta di spazi appositamente (la loro sostituzione con + invece di% 20). Per ovviare a questo abbiamo semplicemente utilizzare questo frammento:

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

+1

Ciò darebbe http://www.google.com?q=a+b non http://www.google.com?q=a% 20b come desiderato. – rpcutts

+0

Ah, sì, l'ho scoperto poche settimane dopo. Modificherà la risposta per riflettere ciò che effettivamente finiamo usando – MrCranky

+1

Questo metodo è ora deprezzato, gli utenti dovrebbero specificare un metodo di codifica vedere: http://docs.oracle.com/javase/1.4.2/docs/api/java/net /URLEncoder.html – Aidanc

45

Android ha sempre avuto la classe Uri come parte del SDK: http://developer.android.com/reference/android/net/Uri.html

Si può semplicemente fare qualcosa di simile:

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

ottimo suggerimento - grazie –

+4

Grazie mille! È ridicolo quanto tempo ci vuole a volte per trovare una semplice funzione Java! – Abdo

+1

Sfortunatamente, il metodo encode() è una schifezza quando si tenta di codificare le barre ("/"). Ho appena usato un semplice vecchio String.replace() per completare il lavoro. Era molto schifoso ... searchQuery.replace ("/", "% 2f"); –

4

Ho avuto problemi simili per uno dei miei progetti per creare un oggetto URI da una stringa. Non sono riuscito a trovare nessuna soluzione pulita. Ecco quello che mi si avvicinò con:

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

È possibile utilizzare il seguente costruttore URI invece di specificare una porta, se necessario:

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

Non gestisce la conversione di un punto interrogativo (l'ho provato con l'URL: 'http://www.google.com/ Ti piace lo spam?'e si è preso cura degli spazi, ma non il punto interrogativo alla fine) – kentcdodds

+0

@kentcdodds è perché il punto interrogativo è legale in questo caso. Sono sicuro che se ne aggiungerai un altro dopo, verrebbe convertito – Sebas

33

ho intenzione di aggiungere un suggerimento qui rivolto agli utenti Android. Puoi fare ciò che evita di dover ottenere eventuali librerie esterne. Inoltre, tutte le soluzioni di ricerca/sostituzione dei caratteri suggerite in alcune delle risposte di cui sopra sono pericolose e dovrebbero essere evitate.

dare una prova:

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

Si può vedere che in questo particolare URL, ho bisogno di avere quegli spazi codificati in modo che posso usarlo per una richiesta.

Questo sfrutta un paio di funzioni disponibili nelle classi Android. In primo luogo, la classe URL può rompere un url nei suoi componenti corretti, quindi non c'è bisogno che tu esegua operazioni di ricerca/sostituzione delle stringhe. In secondo luogo, questo approccio sfrutta la caratteristica della classe URI di componenti di escape appropriati quando si costruisce un URI tramite componenti anziché da una singola stringa.

La bellezza di questo approccio è che puoi prendere qualsiasi stringa di url valida e farla funzionare senza averne alcuna conoscenza specifica da solo.

3

Beh ho provato ad utilizzare

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

Spero che questo sia quello che in realtà cercando?

+0

Grazie amico. Ha funzionato! –

+0

Questa è la risposta che stavo cercando e non richiede alcuna dipendenza dalle librerie esterne. –

+1

No, questa è una risposta sbagliata. 'URLDecoder.decode (" per convertire "," UTF-8 ")' restituisce "per convertire" e 'URLDecoder.decode (" in% 20convert "," UTF-8 ")' restituisce "per convertire". Quindi questo fa l'opposto di ciò che la domanda sta ponendo. –

13

Anche se questo è un vecchio post con una risposta già accettata, inserisco la mia risposta alternativa perché funziona bene per il presente problema e sembra che nessuno abbia menzionato questo metodo.

Con la libreria java.net.URI:

URI uri = URI.create(URLString); 

E se volete una stringa URL in formato ad esso corrispondente:

String validURLString = uri.toASCIIString(); 

A differenza di molti altri metodi (ad es java.net. URLEncoder) questo sostituisce solo caratteri ASCII non sicuri (come ç, é ...).


Nell'esempio precedente, se URLString è la seguente String:

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

risultante validURLString sarà:

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

quali è un URL ben formattata.

+1

la tua risposta era quella che stavo cercando, non potevo estrarre il parametro per vari motivi e questo è l'unico metodo che ha funzionato veramente. – Ramin

+0

E tutti dovrebbero dare un'occhiata alla documentazione quando si tratta di eccezioni http://developer.android.com/reference/java/net/URI.html#create(java.lang.String) –

+0

Questo non sembra convertire citazioni? vale a dire "" – behelit

0

ho finito per usare il 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()); 
} 

uscita sarà:

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