2009-02-21 11 views
66

Ich versuche, ein java.net.URI Objekt von einem String zu bekommen. Die Zeichenfolge enthält einige Zeichen, die durch ihre prozentualen Escape-Sequenzen ersetzt werden müssen. Aber wenn ich URLEncoder verwende, um die Zeichenfolge mit UTF-8-Codierung zu codieren, werden sogar die/mit ihren Escape-Sequenzen ersetzt.Java - String in ein gültiges URI-Objekt konvertieren

Wie kann ich eine gültige codierte URL von einem String-Objekt erhalten?

http://www.google.com?q=a b gibt http% 3A% 2F% 2www.google.com ... während ich die Ausgabe wollen http://www.google.com?q=a%20b

sein Kann mir bitte jemand sagen, wie dies zu erreichen.

Ich versuche, dies in einer Android-App zu tun. So habe ich Zugang zu einer begrenzten Anzahl von Bibliotheken.

Antwort

55

Sie könnten versuchen: org.apache.commons.httpclient.util.URIUtil.encodeQuery in Apache commons-httpclient Projekt

wie folgt aus (siehe URIUtil):

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

werden wird:

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

Sie können natürlich auch selber machen, aber URI Parsing kann ziemlich chaotisch werden ...

+0

Dank Hans. Ich versuche das in einer Android App zu tun. So habe ich Zugang zu einer begrenzten Anzahl von Bibliotheken. Hast du noch andere Vorschläge? Danke nochmal – lostInTransit

+2

Vielleicht könntest du dir die Quelle der URIUtil-Klasse ansehen (sie ist immerhin Open Source). Ich würde annehmen, dass es möglich ist, den notwendigen Code aus dieser Klasse zu extrahieren. –

+6

Das spitz zulaufende Projekt (Apache commons-httpclient) "ist jetzt Ende des Lebens". Es wurde teilweise durch [HttpComponents-httpclient] (http://hc.apache.org/httpcomponents-client-ga) ersetzt, aber ich konnte keine äquivalente Methode in der neuen API finden. – dgiugg

4

Sie können Verwenden Sie die Konstruktoren mit mehreren Argumenten der Klasse URI. Von URI javadoc:

Die Konstruktoren mit mehreren Argumenten geben unzulässige Zeichen an, die für die Komponenten erforderlich sind, in denen sie angezeigt werden. Das Prozentzeichen ('%') wird immer von diesen Konstruktoren zitiert. Alle anderen Zeichen bleiben erhalten.

Also, wenn Sie verwenden

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

Dann sind Sie http:www.google.com?q=a%20b bekommen, was nicht ganz richtig ist, aber es ist ein wenig näher.

Wenn Sie wissen, dass die Zeichenfolge nicht URL-Fragmente (zB http://example.com/page#anchor) haben, dann können Sie den folgenden Code verwenden zu bekommen, was Sie wollen:

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

Um sicher zu sein, sollten Sie die Zeichenfolge scannen für # Zeichen, aber das sollte Sie beginnen.

1

Der java.net Blog hatte neulich eine Klasse, die vielleicht getan hat, was Sie wollen (aber es ist im Moment nicht erreichbar, also kann ich nicht nachsehen).

da Dieser Gutscheincode wahrscheinlich modifiziert werden könnte, zu tun, was Sie wollen:

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

Hier ist die eine, die ich von Java dachte.net: https://urlencodedquerystring.dev.java.net/

9

Wenn Sie keine Bibliotheken mögen, wie wäre es damit?

Beachten Sie, dass Sie diese Funktion nicht für die gesamte URL verwenden sollten, sondern stattdessen für die Komponenten ... z. nur die "a b" -Komponente, wie Sie die URL aufbauen - sonst wird der Computer nicht wissen, welche Zeichen eine besondere Bedeutung haben sollen und welche eine wörtliche Bedeutung haben sollen.

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

Dies funktioniert nicht (zumindest in einigen Fällen). Z.B. Das Zeichen 'Š' wird als '% M1' codiert, sollte jedoch als '% C5% A0' codiert werden. – mindas

+0

Dies funktioniert auch nicht für Zeichen wie Tab. Ich würde vorschlagen, dass dies geändert wird, um unsicher zu sein, wenn es [A-Za-z0-9 _-. ~] Nicht zusammenbringt. Siehe http://en.wikipedia.org/wiki/Percent-encoding – Gray

1

Oder vielleicht könnten Sie diese Klasse verwenden:

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

die in Android seit API-Ebene 1.

Ärgerlicher jedoch vorhanden ist, behandelt es Räume speziell (ersetzt sie mit + anstelle von% 20). Um diese Runde verwenden wir einfach dieses Fragment:

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

+1

Dies würde http://www.google.com?q=a+b nicht http://www.google.com?q=a% 20b wie gewünscht. – rpcutts

+0

Ah, ja, fand ich selbst ein paar Wochen danach. Ändert die Antwort so, dass sie widerspiegelt, was wir tatsächlich verwenden – MrCranky

+1

Diese Methode wird jetzt abgeschrieben, Benutzer sollten eine Methode zum Verschlüsseln angeben: http://docs.oracle.com/javase/1.4.2/docs/api/java/net /URLEncoder.html – Aidanc

45

Android hat immer hatte die Uri-Klasse als Teil des SDK: http://developer.android.com/reference/android/net/Uri.html

Sie können einfach so etwas wie:

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

ausgezeichneter Vorschlag - danke –

+4

Vielen Dank! Es ist lächerlich, wie lange es manchmal dauert, eine einfache Java-Funktion zu finden! – Abdo

+1

Leider ist die Methode encode() ein Mist, wenn man versucht, Schrägstriche ("/") zu kodieren. Ich habe nur eine einfache alte String.replace() verwendet, um den Job zu erledigen. Das war sehr lahm ... searchQuery.replace ("/", "% 2f"); –

4

Ich hatte ähnliche Probleme für eines meiner Projekte, um ein URI-Objekt aus einer Zeichenfolge zu erstellen. Ich konnte auch keine saubere Lösung finden. Hier ist, was ich kam mit:

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

Sie können den folgenden URI Konstruktor verwenden stattdessen einen Port angeben, falls erforderlich:

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

Verarbeitet kein Fragezeichen (Ich habe es mit der URL versucht: 'http://www.google.com/Do magst du Spam?'und es kümmerte sich um die Leerzeichen, aber nicht das Fragezeichen am Ende) – kentcdodds

+0

@kentcdodds es ist, weil das Fragezeichen in diesem Fall legal ist. Ich bin mir sicher, dass, wenn Sie ein anderes nachher hinzufügen, es – Sebas

33

Ich werde einen Vorschlag hinzufügen hier bei Android-Nutzer richtet. Sie können dies tun, wodurch Sie keine externen Bibliotheken benötigen. Außerdem sind alle Such-/Ersatzzeichen-Lösungen, die in einigen der obigen Antworten vorgeschlagen werden, gefährlich und sollten vermieden werden.

dieses Probieren Sie:

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

Sie, dass in diesem speziellen URL sehen kann, muss ich codiert diese Räume haben, so dass ich es für eine Anfrage nutzen können.

Dies nutzt einige Funktionen, die Ihnen in Android-Klassen zur Verfügung stehen. Erstens kann die URL-Klasse eine URL in ihre richtigen Komponenten zerlegen, so dass Sie keine Suche/Ersetzung von Zeichenfolgen durchführen müssen. Zweitens nutzt dieser Ansatz den Vorteil der URI-Klassenfunktion, um Komponenten ordnungsgemäß zu entfernen, wenn Sie einen URI über Komponenten und nicht über eine einzige Zeichenfolge erstellen.

Das Schöne an diesem Ansatz ist, dass Sie jeden gültigen URL-String verwenden können, ohne dass Sie dafür spezielle Kenntnisse benötigen.

3

Nun habe ich versucht,

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

Ich hoffe, mit diesem ist, was Sie wirklich suchen?

+0

sein würde, Danke Mann. Das hat funktioniert! –

+0

Dies ist die Antwort, nach der ich gesucht habe und benötigt keine Abhängigkeit von externen Bibliotheken. –

+1

Nein, das ist falsche Antwort. 'URLDecoder.decode (" umwandeln "," UTF-8 ")' returns "zum konvertieren" und 'URLDecoder.decode (" zu% 20convert "," UTF-8 ")' returns "zum konvertieren". Das ist das Gegenteil von dem, was die Frage stellt. –

13

Auch wenn dies ein alter Post mit einer bereits akzeptierten Antwort ist, poste ich meine alternative Antwort, weil es gut für das vorliegende Problem funktioniert und es scheint, dass niemand diese Methode erwähnt.

Mit der java.net.URI Bibliothek:

URI uri = URI.create(URLString); 

Und wenn Sie ein URL-formatierten String zu wollen, dass es entsprechend:

String validURLString = uri.toASCIIString(); 

Im Gegensatz zu vielen anderen Methoden (zB java.net. URLEncoder) Dieser ersetzt nur unsichere ASCII-Zeichen (wie ç, é ...).


In dem obigen Beispiel, wenn URLString wird die folgenden String:

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

die resultierenden validURLString wird:

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

was eine gut formatierte URL.

+1

Ihre Antwort war die, die ich suchte, ich konnte den Parameter aus verschiedenen Gründen nicht extrahieren und das ist die einzige Methode, die wirklich funktioniert hat. – Ramin

+0

Und jeder sollte sich auch die Dokumentation ansehen, wenn es um Ausnahmen geht http://developer.android.com/reference/java/net/URI.html#create(java.lang.String) –

+0

Dies scheint nicht zu konvertieren Zitate? " – behelit

0

Ich landete mit dem 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()); 
} 

Ausgang wird sein:

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