Analysieren von Abfragezeichenfolgen unter Android

271

Java EE hat ServletRequest.getParameterValues ​​() .

Auf Nicht-EE-Plattformen gibt URL.getQuery () einfach eine Zeichenfolge zurück.

Was ist der normale Weg, um die Abfragezeichenfolge in einer URL richtig zu analysieren, wenn Sie nicht mit Java EE arbeiten?


< rant >

In den Antworten ist es beliebt, einen eigenen Parser zu erstellen. Dies ist ein sehr interessantes und aufregendes Mikrocodierungsprojekt, aber ich kann nicht sagen, dass es eine gute Idee ist :(

Die folgenden Codefragmente sind im Allgemeinen übrigens fehlerhaft oder fehlerhaft. Sie zu brechen ist eine interessante Übung für den Leser. Und zu den Hackern, die die Websites angreifen, die sie verwenden .

Das Parsen von Abfragezeichenfolgen ist ein genau definiertes Problem, aber das Lesen der Spezifikation und das Verstehen der Nuancen ist nicht trivial. Es ist weitaus besser, einen Plattformbibliothekscodierer die harte Arbeit und das Reparieren für Sie erledigen zu lassen!

< / rant >

Wille
quelle
Könnten Sie eine Beispiel-URL posten, was Sie erhalten getQuery()und was Sie als Ausgabe erhalten möchten?
Thomas Owens
1
Möchten Sie dies von einem Servlet oder einer JSP-Seite aus tun? Ich brauche eine Klarstellung, bevor ich antworte.
ChadNC
1
Müssen Sie auch POST-Parameter analysieren?
Thilo
2
Selbst wenn Sie sich auf J2EE befinden (oder auf SE mit ausgewählten EE-Paketen, die wie ich über OSGi hinzugefügt wurden), könnte diese Frage sinnvoll sein. In meinem Fall werden die Abfragezeichenfolgen / URL-codierten POST-Körper von einem Teil des Systems verarbeitet, der absichtlich unabhängig von Dingen wie ist ServletRequest.
Hanno Fietz
61
Upvoted für <rant />!
Nowaker

Antworten:

65

Seit Android M sind die Dinge komplizierter geworden. Die Antwort von android.net.URI .getQueryParameter () hat einen Fehler, der Leerzeichen vor JellyBean bricht. Apache URLEncodedUtils.parse () funktionierte, wurde jedoch in L veraltet und in M entfernt .

Die beste Antwort ist jetzt UrlQuerySanitizer . Dies existiert seit API Level 1 und existiert immer noch. Außerdem werden Sie über schwierige Themen wie den Umgang mit Sonderzeichen oder wiederholte Werte nachdenken.

Der einfachste Code ist

UrlQuerySanitizer.ValueSanitizer sanitizer = UrlQuerySanitizer.getAllButNullLegal();
// remember to decide if you want the first or last parameter with the same name
// If you want the first call setPreferFirstRepeatedParameter(true);
sanitizer.parseUrl(url);
String value = sanitizer.getValue("paramName"); // get your value

Wenn Sie mit dem Standard-Parsing-Verhalten zufrieden sind, können Sie Folgendes tun:

new UrlQuerySanitizer(url).getValue("paramName")

Sie sollten jedoch sicherstellen, dass Sie verstehen, was das Standard-Parsing-Verhalten ist, da es möglicherweise nicht das ist, was Sie wollen.

Nick Fortescue
quelle
4
URLQuerySanitizer.getAllButNullLegal () gibt UrlQuerySanitizer.ValueSanitizer zurück, nicht UrlQuerySanitizer.
Peter Zhao
31
Aus irgendeinem Grund hat das oben genannte für mich nicht funktioniert, ich musste es nur geringfügig ändern - was es noch einfacher macht:UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(YourStringURL); String value = sanitizer.getValue("parameter");
SeBsZ
3
Nicht arbeiten. UrlQuerySanitizer in SDK-23 hat nur eine Methodesanitize()
Ninja
Dadurch werden Sonderzeichen und Emoji dekodiert _. Ich musste mit stackoverflow.com/a/35638979/1155282
Irshu
Gibt es dafür eine Spring Framework-äquivalente Bibliothek?
Iamjoshua
202

Auf Android:

import android.net.Uri;

[...]

Uri uri=Uri.parse(url_string);
uri.getQueryParameter("para1");
DIYismus
quelle
20
Beachten Sie, dass dies die Uri-Klasse und nicht die URI-Klasse verwendet (Uri ist Teil von android.net, während URI Teil von java.net ist)
Marius
5
Beachten Sie auch, dass vor Ice Cream Sandwich + Zeichen in Werten nicht zu Leerzeichen analysiert werden können.
Rpetrich
@rpetrich tatsächlich sagen die Dokumente, dass der Fehler vor Jelly Bean liegt, einschließlich Ice Cream Sandwich. ref
Big McLargeHuge
64

Unter Android bieten die Apache-Bibliotheken einen Abfrageparser:

http://developer.android.com/reference/org/apache/http/client/utils/URLEncodedUtils.html und http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/ http / client / utils / URLEncodedUtils.html

Wille
quelle
9
Dies ist in der Apache http-Client-Bibliothek nicht nur für Android verfügbar. Übrigens wurde der Link zu Apache geändert. Neueste ist: hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/…
Cristian Vrabie
9
Ärgerlicherweise wird URLEncodedUtils.parse()ein ListWert zurückgegeben, den Sie dann durchlaufen müssten, um den Wert für einen bestimmten Schlüssel zu ermitteln. Es wäre viel schöner, wenn es Mapin BalusCs Antwort ein ähnliches Ergebnis liefern würde.
Asaph
1
@Hanno Fietz meinen Sie Sie vertrauen diese Alternativen? Ich weiß, dass sie fehlerhaft sind. Ich weiß, dass das Hinweisen auf die Fehler, die ich sehe, die Leute nur dazu ermutigen wird, "feste" Versionen zu übernehmen, anstatt selbst nach den Fehlern zu suchen, die ich übersehen habe.
Will
1
@ Will - nun, ich würde niemals einfach nur Ausschnitten vertrauen, die ich von einer Website bekommen habe, und niemand sollte es tun . Aber hier sind diese Schnipsel ziemlich gut rezensiert und kommentiert und daher arewirklich hilfreich. Einfach zu sehen , einige Vorschläge auf , was mit dem Code falsch sein könnte , ist schon eine große Hilfe für mich zu denken. Und wohlgemerkt, ich wollte nicht sagen, dass "Roll your own is better" ist, sondern dass es großartig ist, gutes Material für eine fundierte Entscheidung in meinem eigenen Code zu haben.
Hanno Fietz
8
Ich stelle mir vor, dass parse eine Liste zurückgibt, damit die Positionsreihenfolge beibehalten wird und doppelte Einträge leichter möglich sind.
Dhaag23
26

Hier ist die Antwort von BalusC , die jedoch Ergebnisse kompiliert und zurückgibt:

public static Map<String, List<String>> getUrlParameters(String url)
        throws UnsupportedEncodingException {
    Map<String, List<String>> params = new HashMap<String, List<String>>();
    String[] urlParts = url.split("\\?");
    if (urlParts.length > 1) {
        String query = urlParts[1];
        for (String param : query.split("&")) {
            String pair[] = param.split("=");
            String key = URLDecoder.decode(pair[0], "UTF-8");
            String value = "";
            if (pair.length > 1) {
                value = URLDecoder.decode(pair[1], "UTF-8");
            }
            List<String> values = params.get(key);
            if (values == null) {
                values = new ArrayList<String>();
                params.put(key, values);
            }
            values.add(value);
        }
    }
    return params;
}
dfrankow
quelle
1
JVM-Hinweis: Ich habe eine entsprechende Form in Scala mithilfe von Java-Sammlungen implementiert. Hier ist der Github-Kern: gist.github.com/3504765
Jay Taylor
2
Ich schlage vor , Wechsel String pair[] = param.split("=");in String pair[] = param.split("=", 2);den Schlüssel = Wert - Paar nur auf dem ersten Auftreten zu spalten. Ich glaube, es ist erlaubt, nicht codierte Gleichheitszeichen im Wert zu haben.
Dennie
22

Wenn Sie Jetty-Bibliotheken (Server oder Client) in Ihrem Klassenpfad haben, können Sie die Jetty-Util-Klassen verwenden (siehe Javadoc ), z.

import org.eclipse.jetty.util.*;
URL url = new URL("www.example.com/index.php?foo=bar&bla=blub");
MultiMap<String> params = new MultiMap<String>();
UrlEncoded.decodeTo(url.getQuery(), params, "UTF-8");

assert params.getString("foo").equals("bar");
assert params.getString("bla").equals("blub");
moritz
quelle
13

Wenn Sie sich mit Spring 3.1 oder höher (Huch, hatte gehofft , dass die Unterstützung weiter ging zurück), können Sie die Verwendung UriComponentsund UriComponentsBuilder:

UriComponents components = UriComponentsBuilder.fromUri(uri).build();
List<String> myParam = components.getQueryParams().get("myParam");

components.getQueryParams() gibt a zurück MultiValueMap<String, String>

Hier finden Sie weitere Dokumentationen .

Nick Spacek
quelle
Das ist etwas, wonach ich suche. Meine Frage ist, wie bekomme ich den Uri? Ich bin mit der Wartung von Code festgefahren, den ich nicht viel ändern kann und wir verwenden kein HttpServlet. Verwenden Sie stattdessen nur Anmerkungen und Spring (@Get, @Produces (mediaType) und @Path ("/ dataAsJSON / datafield / {datafield})). Sie müssen nur wissen, wie Sie die Abfragezeichenfolge abrufen, damit ich sie wie in gezeigt analysieren kann dieses Beispiel.
Nelda.techspiress
5

Für ein Servlet oder eine JSP-Seite können Sie mithilfe von request.getParameter ("paramname") Querystring-Schlüssel / Wert-Paare abrufen.

String name = request.getParameter("name");

Es gibt andere Möglichkeiten, aber so mache ich es in allen Servlets und JSP-Seiten, die ich erstelle.

ChadNC
quelle
3
HttpServletRequest ist Teil von J2EE, das er nicht hat. Auch die Verwendung von getParamter () ist nicht wirklich parsing.
Mr. Shiny und New
3
Bitte nehmen Sie sich die Zeit, um den Kommentar zu lesen, in dem ich um Klärung seiner Frage gebeten habe. Diese Antwort ist eine Antwort auf seine Antwort auf den Kommentar, in dem er sagte: "Ich versuche dies auf Android zu tun, aber alle Antworten auf allen Plattformen wären nützliche Antworten, die Hinweise geben könnten (auch auf andere, die darauf stoßen könnten Frage) also nicht zurückhalten! " Ich beantwortete seine Frage aufgrund dieses Kommentars. Wenn Sie nichts Nützliches zum Hinzufügen haben, fügen Sie nichts hinzu
ChadNC
1
Sei nicht zu verärgert. "Dies beantwortet die Frage nicht" ist nützlich, IMO.
Mr. Shiny und New
1
Es spielt keine Rolle, ob Android oder nicht, die Frage ist, wie ein String mit URL analysiert und URL-Parameter daraus abgerufen werden können. Was Sie hier portieren, ist Teil der Servlet-API, in der der Servlet-Container eingehende Parameter aus der HTTP-Anforderung für Sie analysiert. Dies ist irrelevant, da es sich bei der Frage um das Parsen von Zeichenfolgen handelt, die eine URL enthalten, keine HTTP-Anforderung und nicht im Servlet-Container.
MVMN
5

Auf Android, habe ich versucht , @diyism Antwort verwenden , aber ich begegnet das Leerzeichen Ausgabe von @rpetrich angehoben, zum Beispiel: ich ein Formular ausfüllen , wo username = "us+us"und password = "pw pw"verursacht eine URL - Zeichenfolge zu wie folgt aussehen:

http://somewhere?username=us%2Bus&password=pw+pw

Der @ diyism-Code wird jedoch zurückgegeben "us+us"und "pw+pw"erkennt das Leerzeichen nicht. Wenn die URL mit %20dem Leerzeichen neu geschrieben wurde, wird Folgendes identifiziert:

http://somewhere?username=us%2Bus&password=pw%20pw

Dies führt zu folgendem Fix:

Uri uri = Uri.parse(url_string.replace("+", "%20"));
uri.getQueryParameter("para1");
Stephen Quan
quelle
replace(" ", "%20")das fühlt sich falsch an. Aber hat den Trick für mich getan: D
Mārtiņš Briedis
Die korrekte Syntax sollte "irgendein String" sein .replaceAll ("[+]", "% 20");
RRTW
4

Das Parsen der Abfragezeichenfolge ist etwas komplizierter als es scheint, je nachdem, wie verzeihend Sie sein möchten.

Erstens ist die Abfragezeichenfolge ASCII-Bytes. Sie lesen diese Bytes einzeln ein und konvertieren sie in Zeichen. Ist der Charakter? oder & dann signalisiert es den Start eines Parameternamens. Wenn das Zeichen = ist, signalisiert es den Beginn eines Parameterwerts. Wenn das Zeichen% ist, signalisiert es den Beginn eines codierten Bytes. Hier wird es schwierig.

Wenn Sie ein% char einlesen, müssen Sie die nächsten zwei Bytes lesen und sie als hexadezimale Ziffern interpretieren. Das bedeutet, dass die nächsten zwei Bytes 0-9, af oder AF sind. Kleben Sie diese beiden hexadezimalen Ziffern zusammen, um Ihren Bytewert zu erhalten. Aber denken Sie daran, Bytes sind keine Zeichen . Sie müssen wissen, mit welcher Codierung die Zeichen codiert wurden. Das Zeichen é codiert in UTF-8 nicht dasselbe wie in ISO-8859-1. Im Allgemeinen ist es unmöglich zu wissen, welche Codierung für einen bestimmten Zeichensatz verwendet wurde. Ich verwende immer UTF-8, da meine Website so konfiguriert ist, dass immer alles mit UTF-8 bereitgestellt wird, aber in der Praxis können Sie nicht sicher sein. Einige Benutzeragenten teilen Ihnen die Zeichencodierung in der Anforderung mit. Sie können versuchen, dies zu lesen, wenn Sie eine vollständige HTTP-Anfrage haben. Wenn Sie nur eine URL isoliert haben, viel Glück.

Angenommen, Sie verwenden UTF-8 oder eine andere Mehrbyte-Zeichencodierung. Nachdem Sie ein codiertes Byte decodiert haben, müssen Sie es beiseite legen, bis Sie das nächste Byte erfassen. Sie benötigen alle codierten Bytes, die zusammen sind, da Sie nicht jeweils ein Byte richtig url-decodieren können. Legen Sie alle Bytes beiseite, die zusammen sind, und dekodieren Sie sie alle gleichzeitig, um Ihren Charakter zu rekonstruieren.

Außerdem macht es mehr Spaß, wenn Sie nachsichtig sein und Benutzeragenten berücksichtigen möchten, die URLs entstellen. Beispielsweise codieren einige Webmail-Clients Dinge doppelt. Oder verdoppeln Sie die Zeichen? & = (Zum Beispiel :) http://yoursite.com/blah??p1==v1&&p2==v2. Wenn Sie versuchen möchten, mit diesem Problem ordnungsgemäß umzugehen, müssen Sie Ihrem Parser mehr Logik hinzufügen.

Mr. Shiny und New 安 宇
quelle
Das erklärt nicht, wie man querystring Parameterwerte analysiert oder abruft
ChadNC
Richtig, aber etwas umständlich. Dafür haben wir bereits URLDecoder.
BalusC
2
@ChadNC: Im dritten Satz erfahren Sie, wie Sie analysieren: Lesen Sie jeweils ein Byte ein und konvertieren Sie es in Zeichen. Der vierte Satz warnt Sie vor Sonderzeichen. Vielleicht haben Sie die Antwort nicht gelesen?
Mr. Shiny und New
@BalusC: URLDecoder funktioniert, hat jedoch einige Fehlermodi, wenn Sie versuchen, bei der Art der von Ihnen akzeptierten URL nachsichtiger zu sein.
Mr. Shiny und New
1
Einverstanden mit @ Mr.ShinyAndNew Parse-Abfrageparameter ist nicht einfach. Ich unterstütze FIQL und das wird zu einem WIRKLICHEN Schmerz im Arsch. Beispiel: yoursite.com/blah??p1==v1&&p2==v2,p2==v3;p2==v4
rafa.ferreira
4

Unter Android ist es so einfach wie der folgende Code:

UrlQuerySanitizer sanitzer = new UrlQuerySanitizer(url);
String value = sanitzer.getValue("your_get_parameter");

Auch wenn Sie nicht jeden erwarteten Abfrageschlüssel registrieren möchten, verwenden Sie:

sanitzer.setAllowUnregisteredParamaters(true)

Vor dem Anruf:

sanitzer.parseUrl(yourUrl)
Kevin Crain
quelle
4

Ich habe Methoden, um dies zu erreichen:

1) :

public static String getQueryString(String url, String tag) {
    String[] params = url.split("&");
    Map<String, String> map = new HashMap<String, String>();
    for (String param : params) {
        String name = param.split("=")[0];
        String value = param.split("=")[1];
        map.put(name, value);
    }

    Set<String> keys = map.keySet();
    for (String key : keys) {
        if(key.equals(tag)){
         return map.get(key);
        }
        System.out.println("Name=" + key);
        System.out.println("Value=" + map.get(key));
    }
    return "";
}

2) und der einfachste Weg, dies mit der Uri- Klasse zu tun :

public static String getQueryString(String url, String tag) {
    try {
        Uri uri=Uri.parse(url);
        return uri.getQueryParameter(tag);
    }catch(Exception e){
        Log.e(TAG,"getQueryString() " + e.getMessage());
    }
    return "";
}

Dies ist ein Beispiel für die Verwendung einer von zwei Methoden:

String url = "http://www.jorgesys.com/advertisements/publicidadmobile.htm?position=x46&site=reform&awidth=800&aheight=120";      
String tagValue = getQueryString(url,"awidth");

Der Wert von tagValue ist 800

Jorgesys
quelle
3

Unter Android können Sie die statische Methode Uri.parse der Klasse android.net.Uri verwenden , um das schwere Heben durchzuführen . Wenn Sie etwas mit URIs und Absichten tun, sollten Sie es trotzdem verwenden.

Patrick O'Leary
quelle
3

Nur als Referenz, dies ist, was ich am Ende (basierend auf URLEncodedUtils und Rückgabe einer Karte).

Eigenschaften:

  • Es akzeptiert den Teil der Abfragezeichenfolge der URL (Sie können ihn verwenden request.getQueryString()).
  • Eine leere Abfragezeichenfolge erzeugt eine leere Map
  • Ein Parameter ohne Wert (? test) wird einem leeren zugeordnet List<String>

Code:

public static Map<String, List<String>> getParameterMapOfLists(String queryString) {
    Map<String, List<String>> mapOfLists = new HashMap<String, List<String>>();
    if (queryString == null || queryString.length() == 0) {
        return mapOfLists;
    }
    List<NameValuePair> list = URLEncodedUtils.parse(URI.create("http://localhost/?" + queryString), "UTF-8");
    for (NameValuePair pair : list) {
        List<String> values = mapOfLists.get(pair.getName());
        if (values == null) {
            values = new ArrayList<String>();
            mapOfLists.put(pair.getName(), values);
        }
        if (pair.getValue() != null) {
            values.add(pair.getValue());
        }
    }

    return mapOfLists;
}

Ein Kompatibilitätshelfer (Werte werden wie in ServletRequest.getParameterMap () in einem String-Array gespeichert ):

public static Map<String, String[]> getParameterMap(String queryString) {
    Map<String, List<String>> mapOfLists = getParameterMapOfLists(queryString);

    Map<String, String[]> mapOfArrays = new HashMap<String, String[]>();
    for (String key : mapOfLists.keySet()) {
        mapOfArrays.put(key, mapOfLists.get(key).toArray(new String[] {}));
    }

    return mapOfArrays;
}
Dan
quelle
3

Das funktioniert bei mir. Ich bin mir nicht sicher, warum jeder nach einer Karte, Liste> Alles was ich brauchte war eine einfache Namenswertkarte.

Um die Dinge einfach zu halten, habe ich den Build in URI.getQuery () verwendet.

public static Map<String, String> getUrlParameters(URI uri)
    throws UnsupportedEncodingException {
    Map<String, String> params = new HashMap<String, String>();
    for (String param : uri.getQuery().split("&")) {
        String pair[] = param.split("=");
        String key = URLDecoder.decode(pair[0], "UTF-8");
        String value = "";
        if (pair.length > 1) {
            value = URLDecoder.decode(pair[1], "UTF-8");
        }
        params.put(new String(key), new String(value));
    }
    return params;
}
Dave
quelle
1
Wie wäre es mit Formularen mit Mehrfachauswahl? Es ist völlig normal, dass Schlüssel in legitimen Abfragezeichenfolgen (und POST-Formularkörpern) wiederholt werden. Es gibt andere Mängel und Eckfälle, die nicht abgedeckt sind. Viele von ihnen wurden in Kommentaren zu anderen Ansätzen erwähnt. Ich werde es unterlassen, sie darauf hinzuweisen, aus Angst, dass Sie es reparieren, anstatt eine Qualitätsbibliothek zu verwenden, wie in meinem Rant in der Frage angegeben;)
Will
2

Dafür ist Guavas Multimap besser geeignet. Hier ist eine kurze saubere Version:

Multimap<String, String> getUrlParameters(String url) {
        try {
            Multimap<String, String> ret = ArrayListMultimap.create();
            for (NameValuePair param : URLEncodedUtils.parse(new URI(url), "UTF-8")) {
                ret.put(param.getName(), param.getValue());
            }
            return ret;
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }
Pathikrit
quelle
1

Apache AXIS2 verfügt über eine eigenständige Implementierung von QueryStringParser.java. Wenn Sie Axis2 nicht verwenden, laden Sie einfach den Quellcode und den Testfall von hier herunter -

http://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/transport/http/util/QueryStringParser.java

http://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/modules/kernel/test/org/apache/axis2/transport/http/util/QueryStringParserTest.java

Sripathi Krishnan
quelle
1

Ursprünglich hier beantwortet

Unter Android gibt es die Uri-Klasse im Paket android.net . Beachten Sie, dass Uri Teil von android.net ist, während URI Teil von java.net ist.

Die Uri-Klasse verfügt über viele Funktionen zum Extrahieren von Abfrage-Schlüssel-Wert-Paaren. Geben Sie hier die Bildbeschreibung ein

Die folgende Funktion gibt Schlüssel-Wert-Paare in Form von HashMap zurück.

In Java:

Map<String, String> getQueryKeyValueMap(Uri uri){
    HashMap<String, String> keyValueMap = new HashMap();
    String key;
    String value;

    Set<String> keyNamesList = uri.getQueryParameterNames();
    Iterator iterator = keyNamesList.iterator();

    while (iterator.hasNext()){
        key = (String) iterator.next();
        value = uri.getQueryParameter(key);
        keyValueMap.put(key, value);
    }
    return keyValueMap;
}

In Kotlin:

fun getQueryKeyValueMap(uri: Uri): HashMap<String, String> {
        val keyValueMap = HashMap<String, String>()
        var key: String
        var value: String

        val keyNamesList = uri.queryParameterNames
        val iterator = keyNamesList.iterator()

        while (iterator.hasNext()) {
            key = iterator.next() as String
            value = uri.getQueryParameter(key) as String
            keyValueMap.put(key, value)
        }
        return keyValueMap
    }
Ramakrishna Joshi
quelle
0

Ich glaube nicht, dass es einen in JRE gibt. Sie können ähnliche Funktionen in anderen Paketen wie Apache HttpClient finden. Wenn Sie keine anderen Pakete verwenden, müssen Sie nur Ihre eigenen schreiben. Es ist nicht so schwer. Hier ist was ich benutze,

public class QueryString {

 private Map<String, List<String>> parameters;

 public QueryString(String qs) {
  parameters = new TreeMap<String, List<String>>();

  // Parse query string
     String pairs[] = qs.split("&");
     for (String pair : pairs) {
            String name;
            String value;
            int pos = pair.indexOf('=');
            // for "n=", the value is "", for "n", the value is null
         if (pos == -1) {
          name = pair;
          value = null;
         } else {
       try {
        name = URLDecoder.decode(pair.substring(0, pos), "UTF-8");
              value = URLDecoder.decode(pair.substring(pos+1, pair.length()), "UTF-8");            
       } catch (UnsupportedEncodingException e) {
        // Not really possible, throw unchecked
           throw new IllegalStateException("No UTF-8");
       }
         }
         List<String> list = parameters.get(name);
         if (list == null) {
          list = new ArrayList<String>();
          parameters.put(name, list);
         }
         list.add(value);
     }
 }

 public String getParameter(String name) {        
  List<String> values = parameters.get(name);
  if (values == null)
   return null;

  if (values.size() == 0)
   return "";

  return values.get(0);
 }

 public String[] getParameterValues(String name) {        
  List<String> values = parameters.get(name);
  if (values == null)
   return null;

  return (String[])values.toArray(new String[values.size()]);
 }

 public Enumeration<String> getParameterNames() {  
  return Collections.enumeration(parameters.keySet()); 
 }

 public Map<String, String[]> getParameterMap() {
  Map<String, String[]> map = new TreeMap<String, String[]>();
  for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
   List<String> list = entry.getValue();
   String[] values;
   if (list == null)
    values = null;
   else
    values = (String[]) list.toArray(new String[list.size()]);
   map.put(entry.getKey(), values);
  }
  return map;
 } 
}
ZZ Coder
quelle
Wie ist der Weg mit den Apache-Klassen?
Will
1
Sie können die parse () -Methode verwenden: hc.apache.org/httpcomponents-client/httpclient/apidocs/org/…
ZZ Coder
3
Bitte fügen Sie den Apache Commons-Link in eine eigene Antwort ein, damit ich ihn abstimmen kann.
Itsadok
0

Basierend auf der Antwort von BalusC habe ich einen Beispiel-Java-Code geschrieben:

    if (queryString != null)
    {
        final String[] arrParameters = queryString.split("&");
        for (final String tempParameterString : arrParameters)
        {
            final String[] arrTempParameter = tempParameterString.split("=");
            if (arrTempParameter.length >= 2)
            {
                final String parameterKey = arrTempParameter[0];
                final String parameterValue = arrTempParameter[1];
                //do something with the parameters
            }
        }
    }
Andreas
quelle
0
public static Map <String, String> parseQueryString (final URL url)
        throws UnsupportedEncodingException
{
    final Map <String, String> qps = new TreeMap <String, String> ();
    final StringTokenizer pairs = new StringTokenizer (url.getQuery (), "&");
    while (pairs.hasMoreTokens ())
    {
        final String pair = pairs.nextToken ();
        final StringTokenizer parts = new StringTokenizer (pair, "=");
        final String name = URLDecoder.decode (parts.nextToken (), "ISO-8859-1");
        final String value = URLDecoder.decode (parts.nextToken (), "ISO-8859-1");
        qps.put (name, value);
    }
    return qps;
}
Wafna
quelle
0

mit Guave:

Multimap<String,String> parseQueryString(String queryString, String encoding) {
    LinkedListMultimap<String, String> result = LinkedListMultimap.create();

    for(String entry : Splitter.on("&").omitEmptyStrings().split(queryString)) {
        String pair [] = entry.split("=", 2);
        try {
            result.put(URLDecoder.decode(pair[0], encoding), pair.length == 2 ? URLDecoder.decode(pair[1], encoding) : null);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    return result;
}
Tyson
quelle
0

Hier antworten, weil dies ein beliebter Thread ist. Dies ist eine saubere Lösung in Kotlin, die die empfohlene UrlQuerySanitizerAPI verwendet. Siehe die offizielle Dokumentation . Ich habe einen String Builder hinzugefügt, um die Parameter zu verketten und anzuzeigen.

    var myURL: String? = null
    // if the url is sent from a different activity where you set it to a value
    if (intent.hasExtra("my_value")) {
        myURL = intent.extras.getString("my_value")
    } else {
        myURL = intent.dataString
    }

    val sanitizer = UrlQuerySanitizer(myURL)
    // We don't want to manually define every expected query *key*, so we set this to true
    sanitizer.allowUnregisteredParamaters = true
    val parameterNamesToValues: List<UrlQuerySanitizer.ParameterValuePair> = sanitizer.parameterList
    val parameterIterator: Iterator<UrlQuerySanitizer.ParameterValuePair> = parameterNamesToValues.iterator()

    // Helper simply so we can display all values on screen
    val stringBuilder = StringBuilder()

    while (parameterIterator.hasNext()) {
        val parameterValuePair: UrlQuerySanitizer.ParameterValuePair = parameterIterator.next()
        val parameterName: String = parameterValuePair.mParameter
        val parameterValue: String = parameterValuePair.mValue

        // Append string to display all key value pairs
        stringBuilder.append("Key: $parameterName\nValue: $parameterValue\n\n")
    }

    // Set a textView's text to display the string
    val paramListString = stringBuilder.toString()
    val textView: TextView = findViewById(R.id.activity_title) as TextView
    textView.text = "Paramlist is \n\n$paramListString"

    // to check if the url has specific keys
    if (sanitizer.hasParameter("type")) {
        val type = sanitizer.getValue("type")
        println("sanitizer has type param $type")
    }
Jungledev
quelle
-2

Diese Methode verwendet die Uri- und Rückgabekarte von Par-Name und Par-Wert

  public static Map<String, String> getQueryMap(String uri) {

    String queryParms[] = uri.split("\\?");

    Map<String, String> map = new HashMap<>();// 

    if (queryParms == null || queryParms.length == 0) return map;

    String[] params = queryParms[1].split("&");
    for (String param : params) {
        String name = param.split("=")[0];
        String value = param.split("=")[1];
        map.put(name, value);
    }
    return map;
}
FAHAD HAMMAD ALOTAIBI
quelle
1
Wie oben erwähnt, kann dies trivial zum Absturz gebracht werden. Machen Sie sich keine Sorgen um die Reparatur, sondern verwenden Sie stattdessen eine professionelle Utility-Bibliothek.
Will
-3

Sie sagen "Java", aber "nicht Java EE". Meinen Sie damit, dass Sie JSP und / oder Servlets verwenden, aber keinen vollständigen Java EE-Stack? Wenn dies der Fall ist, sollte Ihnen weiterhin request.getParameter () zur Verfügung stehen.

Wenn Sie meinen, Sie schreiben Java, aber Sie schreiben keine JSPs oder Servlets oder Sie verwenden nur Java als Referenzpunkt, aber Sie befinden sich auf einer anderen Plattform, die keine integrierte Parameteranalyse hat ... Wow , das klingt nur nach einer unwahrscheinlichen Frage, aber wenn ja, wäre das Prinzip:

xparm=0
word=""
loop
  get next char
  if no char
    exit loop
  if char=='='
    param_name[xparm]=word
    word=""
  else if char=='&'
    param_value[xparm]=word
    word=""
    xparm=xparm+1
  else if char=='%'
    read next two chars
    word=word+interpret the chars as hex digits to make a byte
  else
    word=word+char

(Ich könnte Java-Code schreiben, aber das wäre sinnlos, denn wenn Sie Java zur Verfügung haben, können Sie einfach request.getParameters verwenden.)

Jay
quelle
Achten Sie beim URL-Decodieren der Hex-Ziffern auf die Zeichencodierung.
Mr. Shiny und New
Es ist Android, daher Java, aber nicht J2EE.
Andrzej Doyle
Ich habe vergessen zu erwähnen: Sie müssen auch nach "+" suchen, was in ein Leerzeichen übersetzt werden soll. Eingebettete Leerzeichen sind in einer Abfragezeichenfolge unzulässig.
Jay