解析Android上的查询字符串

Wil*_*ill 269 java url parsing android

Java EE具有ServletRequest.getParameterValues().

在非EE平台上,URL.getQuery()只返回一个字符串.

什么是正确分析查询字符串中当URL以正常的方式不是基于Java EE?


< rant >

在尝试制作自己的解析器的答案中很受欢迎.这是一个非常有趣和令人兴奋的微编码项目,但我不能说这是一个好主意 :(

下面的代码片段通常有缺陷或破损,顺便说一下.打破它们对读者来说是一个有趣的练习. 并且黑客攻击使用它们的网站.

解析查询字符串是一个定义明确的问题,但阅读规范和理解细微差别并非易事.让一些平台库编码器做出艰苦的工作,并为您做好修复,这要好得多!

< / rant >

diy*_*ism 202

在Android上:

import android.net.Uri;

[...]

Uri uri=Uri.parse(url_string);
uri.getQueryParameter("para1");
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这使用的是Uri类而不是URI类(Uri是android.net的一部分,而URI是java.net的一部分) (19认同)
  • 另请注意,在Ice Cream Sandwich之前,无法将值中的+字符解析为空格字符. (5认同)

Wil*_*ill 64

在Android上,Apache库提供了一个Query解析器:

http://developer.android.com/reference/org/apache/http/client/utils/URLEncodedUtils.htmlhttp://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/ HTTP /客户/ utils的/ URLEncodedUtils.html

  • 这可以在apache http客户端库中找到,而不仅仅是在Android上.顺便说一下,apache的链接已经改变了.最新的是:http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URLEncodedUtils.html (9认同)
  • 令人讨厌的`URLEncodedUtils.parse()`返回一个`List`,然后你必须循环才能找到特定键的值.如果它像BalusC的答案那样返回一个"地图"会更好. (9认同)
  • 我想parse返回一个列表,以便它保持位置排序,更容易允许重复的条目. (8认同)

Nic*_*cue 61

因为Android M的东西变得更加复杂.android.net.URI .getQueryParameter()的答案有一个在JellyBean之前打破空格的bug. 阿帕奇URLEncodedUtils.parse()工作,但以L弃用,并以M删除.

所以现在最好的答案是UrlQuerySanitizer.这已经存在于API级别1并且仍然存在.它还会让您考虑棘手的问题,例如如何处理特殊字符或重复值.

最简单的代码是

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
Run Code Online (Sandbox Code Playgroud)

  • 出于某种原因,上面的内容对我来说不起作用,我只需稍微修改一下 - 这使得它更容易:`UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(YourStringURL);``String value = sanitizer.getValue("parameter"); ` (29认同)
  • URLQuerySanitizer.getAllButNullLegal()返回UrlQuerySanitizer.ValueSanitizer,而不是UrlQuerySanitizer. (4认同)
  • 不行.sdk-23中的`UrlQuerySanitizer`只有一个方法`sanitize()` (3认同)

dfr*_*kow 26

这是BalusC的答案,但它编译并返回结果:

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我建议将`String pair [] = param.split("=");`更改为`String pair [] = param.split("=",2);`仅在第一次出现时拆分key = value对.我相信它允许有未编码的等值符号. (2认同)

mor*_*itz 22

如果你的类路径上有jetty(服务器或客户端)库,你可以使用jetty util类(参见javadoc),例如:

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");
Run Code Online (Sandbox Code Playgroud)


Nic*_*cek 13

如果你使用的是Spring 3.1或更高版本(yikes,希望支持能够进一步发展),你可以使用UriComponentsUriComponentsBuilder:

UriComponents components = UriComponentsBuilder.fromUri(uri).build();
List<String> myParam = components.getQueryParams().get("myParam");
Run Code Online (Sandbox Code Playgroud)

components.getQueryParams() 返回一个 MultiValueMap<String, String>

这是一些更多的文档.


Jor*_*sys 6

我有方法来实现这一点:

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 "";
}
Run Code Online (Sandbox Code Playgroud)

2)最简单的方法是使用Uri类:

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 "";
}
Run Code Online (Sandbox Code Playgroud)

这是如何使用两种方法之一的示例:

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

tagValue 的值为800


Cha*_*dNC 5

对于servlet或JSP页面,您可以使用request.getParameter("paramname")获取查询字符串键/值对

String name = request.getParameter("name");
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以做到,但这就是我在我创建的所有servlet和jsp页面中的方式.

  • HttpServletRequest是他没有的J2EE的一部分.另外使用getParamter()并不是真正解析. (3认同)
  • 请花点时间阅读我要求澄清他的问题的评论.这个答案是为了回应他对该评论的回答,他在评论中表示,"我试图在Android上做到这一点,但所有平台上的所有答案都是有用的答案,可能会指出(也可能会遇到其他人)问题)所以不要忍住!" 我根据这个评论回答了他的问题.如果您没有任何有用的添加内容,请不要添加任何内容 (3认同)

Ste*_*uan 5

在Android上,我尝试使用@diyism的答案,但我遇到了由@rpetrich提出的空格字符的问题,例如:我填写一个表格,username = "us+us"password = "pw pw"导致URL字符串的样子:

http://somewhere?username=us%2Bus&password=pw+pw
Run Code Online (Sandbox Code Playgroud)

但是,@diyism 代码返回"us+us"and "pw+pw",即它不检测空格字符。如果 URL 被改写%20为空格字符被识别:

http://somewhere?username=us%2Bus&password=pw%20pw
Run Code Online (Sandbox Code Playgroud)

这导致以下修复:

Uri uri = Uri.parse(url_string.replace("+", "%20"));
uri.getQueryParameter("para1");
Run Code Online (Sandbox Code Playgroud)