Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中URI查询字符串的解码_Java_Decoding_Query String - Fatal编程技术网

Java中URI查询字符串的解码

Java中URI查询字符串的解码,java,decoding,query-string,Java,Decoding,Query String,我需要解码包含查询字符串的URI;预期的输入/输出行为如下所示: abstract class URIParser { /** example input: * something?alias=pos&FirstName=Foo+A%26B%3DC&LastName=Bar */ URIParser(String input) { ... } /** should return "something" for the examp

我需要解码包含查询字符串的URI;预期的输入/输出行为如下所示:

abstract class URIParser
{       
    /** example input: 
      * something?alias=pos&FirstName=Foo+A%26B%3DC&LastName=Bar */
    URIParser(String input) { ... }
    /** should return "something" for the example input */
    public String getPath(); 
    /** should return a map 
      * {alias: "pos", FirstName: "Foo+A&B=C", LastName: "Bar"} */
    public Map<String,String> getQuery();
}
抽象类解析器
{       
/**输入示例:
*什么?别名=pos&FirstName=Foo+A%26B%3DC&LastName=Bar*/
URIParser(字符串输入){…}
/**应该为示例输入返回“something”*/
公共字符串getPath();
/**你应该还一张地图
*{别名:“pos”,名字:“Foo+A&B=C”,姓氏:“Bar”}*/
公共地图getQuery();
}
我尝试使用,但它似乎解码了查询字符串,因此在上面的示例中,我只剩下“alias=pos&FirstName=Foo+A&B=C&LastName=Bar”,因此“&”是查询分隔符还是查询组件中的字符存在歧义

编辑:我刚刚尝试过,但它没有进行编码,因此我可以使用
拆分查询字符串,但我该怎么办?Javascript有,我似乎无法在Java中找到相应的方法

有什么建议吗?我宁愿不使用任何新的库。

请参见class

使用

URLDecoder.decode(proxyRequestParam.replace("+", "%2B"), "UTF-8")
          .replace("%2B", "+")
模拟
解码组件
。Java的
URLDecoder
将加号解码为一个空格,这个空格不是您想要的,因此您需要replace语句

警告:如@xehpuk所指出,如果原始文件(pre-x-www-form-urlencoded)包含该字符串,则末尾的
.replace(“%2B”和“+”)
将损坏您的数据


关于+符号的问题:

我创建了一个helper类,该类根据@janb的答案包装URLDecover函数

import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class DateDecoder {

    private static final String KEY_DATE = "datekey";

    private static final SimpleDateFormat SIMPLE_DATE_FORMAT =
            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US);


    public static void main(String[] args) throws UnsupportedEncodingException {
        try {
            Uri uri = Uri.parse("http://asdf.com?something=12345&" +
                    KEY_DATE +"=2016-12-24T12:00:00+01:00");

            System.out.println("parsed date: " + DateDecoder.createDate(uri)); // parsed date: Sat Dec 24 12:00:00 GMT+01:00 2016
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Nullable
    public static Date createDate(@Nullable Uri data) {
        if (data != null) {
            try {
                String withPlus = decodeButKeepPlus(KEY_DATE, data.getEncodedQuery());
                if (!TextUtils.isEmpty(withPlus)) {
                    return SIMPLE_DATE_FORMAT.parse(withPlus);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * copied from android.net.Uri.java
     */
    @Nullable
    public static String decodeButKeepPlus(String encodedKey, String completeEncodedQuery)
            throws UnsupportedEncodingException {

        final int length = completeEncodedQuery.length();
        int start = 0;
        do {
            int nextAmpersand = completeEncodedQuery.indexOf('&', start);
            int end = nextAmpersand != -1 ? nextAmpersand : length;

            int separator = completeEncodedQuery.indexOf('=', start);
            if (separator > end || separator == -1) {
                separator = end;
            }

            if (separator - start == encodedKey.length()
                    && completeEncodedQuery.regionMatches(start, encodedKey, 0, encodedKey.length())) {
                if (separator == end) {
                    return "";
                } else {
                    String encodedValue = completeEncodedQuery.substring(separator + 1, end);
                    if (!TextUtils.isEmpty(encodedValue)) {
                        return URLDecoder.decode(encodedValue.replace("+", "%2B"), "UTF-8").replace("%2B", "+");
                    }
                }
            }

            // Move start to end of name.
            if (nextAmpersand != -1) {
                start = nextAmpersand + 1;
            } else {
                break;
            }
        } while (true);
        return null;
    }

}

js encodeURIComponent编码的字符串应该只是一个路径,没有模式和其他内容。但是,它仍然是java.net.URI的有效输入。因此java.net.URI将为我们做所有事情,然后它的路径就是我们想要的。

既然您不想引入新的lib,我可以问一下您是在哪种环境中接收这些URI的吗?应该注意的是,在使用它之前,您应该识别查询部分并将参数拆分为键/值对,但是它会根据HTML
application/x-www-form-urlencoded
spec将百分比编码值解码为给定的编码(参见UTF-8)。请始终将答案放在答案中。链接会产生额外的工作,不能保证链接会一直工作。这应该是公认的答案。URI按原样处理+符号,而空格编码为%20。URLDecoder与URI编码的字符串不兼容,因为它将+和%20解码到一个空格中。第二次替换的意义是什么?解码后,字符串中不再有“%2B”的任何实例,因为它们都将被替换为“+”,因此替换将不会匹配任何内容。关键是,您不希望解码字符串中包含编码字符。因为Java不像JavaScript那样解码+-符号,所以我首先对+-符号进行编码,这样Java就不会触及它,然后将%2B解码为+-符号。简而言之:如果我不这样做,解码后的URL将不会包含原始的+-符号(因为Java会在解码阶段丢失它们)。@janb-我认为第二次替换是不必要的,因为
decode
方法已经将找到的
%2B
转换为
+
。第一次替换是必要的,以阻止它将
+
转换为空格。@StevePowell第二次替换不仅是不必要的,而且是错误的。虽然这段代码可能会解决这个问题,但如何以及为什么解决这个问题将真正有助于提高您的帖子质量,并可能导致更多的投票。请记住,你是在将来回答读者的问题,而不仅仅是现在提问的人。请在回答中添加解释,并说明适用的限制和假设。
var reqParam =  URLDecoder.decode(reqParam, "UTF-8")
new java.net.URI(proxyRequestParam).getPath()