Java Android:如何将带有空格的 URL 字符串解析为 URI 对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2593214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:38:16  来源:igfitidea点击:

Android: how to parse URL String with spaces to URI object?

javaandroidurlurihttprequest

提问by whlk

I have a string representing an URL containing spaces and want to convert it to an URI object. If I simply try to create it via

我有一个表示包含空格的 URL 的字符串,并希望将其转换为 URI 对象。如果我只是尝试通过创建它

String myString = "http://myhost.com/media/File Name that has spaces inside.mp3";
URI myUri = new URI(myString);

it gives me

它给了我

java.net.URISyntaxException: Illegal character in path at index X

where index Xis the position of the first space in the URL string.

其中 indexX是 URL 字符串中第一个空格的位置。

How can i parse myStringinto a URIobject?

我怎样才能解析myString成一个URI对象?

采纳答案by BalusC

You should in fact URI-encodethe "invalid" characters. Since the string actually contains the complete URL, it's hard to properly URI-encode it. You don't know which slashes /should be taken into account and which not. You cannot predict that on a raw Stringbeforehand. The problem really needs to be solved at a higher level. Where does that Stringcome from? Is it hardcoded? Then just change it yourself accordingly. Does it come in as user input? Validate it and show error, let the user solve itself.

实际上,您应该“无效”字符进行 URI 编码。由于字符串实际上包含完整的 URL,因此很难对其进行正确的 URI 编码。您不知道/应该考虑哪些斜线,哪些不应该考虑。您无法String事先预测原始数据。这个问题确实需要在更高的层次上解决。这是String从哪里来的?它是硬编码的吗?然后自己相应地改变它。它是作为用户输入进来的吗?验证并显示错误,让用户自行解决。

At any way, if you can ensure that it are onlythe spaces in URLs which makes it invalid, then you can also just do a string-by-string replace with %20:

无论如何,如果您可以确保只有URL 中的空格使其无效,那么您也可以使用%20以下内容逐个字符串替换:

URI uri = new URI(string.replace(" ", "%20"));

Or if you can ensure that it's onlythe part after the last slash which needs to be URI-encoded, then you can also just do so with help of android.net.Uriutility class:

或者,如果您可以确保它只是需要进行 URI 编码的最后一个斜杠之后的部分,那么您也可以在android.net.Uri实用程序类的帮助下这样做:

int pos = string.lastIndexOf('/') + 1;
URI uri = new URI(string.substring(0, pos) + Uri.encode(string.substring(pos)));

Do note that URLEncoderis insuitable for the task as it's designed to encode query string parameter names/values as per application/x-www-form-urlencodedrules (as used in HTML forms). See also Java URL encoding of query string parameters.

请注意,这URLEncoder不适合该任务,因为它旨在根据application/x-www-form-urlencoded规则(如在 HTML 表单中使用)对查询字符串参数名称/值进行编码。另请参阅查询字符串参数的 Java URL 编码

回答by Bozho

java.net.URLEncoder.encode(finalPartOfString, "utf-8");

This will URL-encodethe string.

这将对字符串进行 URL 编码

finalPartOfStringis the part after the last slash - in your case, the name of the song, as it seems.

finalPartOfString是最后一个斜杠之后的部分 - 在你的情况下,这首歌的名字,看起来。

回答by Phileo99

To handle spaces, @, and other unsafe characters in arbitrary locations in the url path, Use Uri.Builder in combination with a local instance of URL as I have described here:

要处理 url 路径中任意位置的空格、@ 和其他不安全字符,请将 Uri.Builder 与本地 URL 实例结合使用,如我在此处所述:

private Uri.Builder builder;
public Uri getUriFromUrl(String thisUrl) {
    URL url = new URL(thisUrl);
    builder =  new Uri.Builder()
                            .scheme(url.getProtocol())
                            .authority(url.getAuthority())
                            .appendPath(url.getPath());
    return builder.build();
}

回答by siddmuk2005

URL url = Test.class.getResource(args[0]);  // reading demo file path from                                                   
                                            // same location where class                                    
File input=null;
try {
    input = new File(url.toURI());
} catch (URISyntaxException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

回答by hadilq

I wrote this function:

我写了这个函数:

public static String encode(@NonNull String uriString) {
    if (TextUtils.isEmpty(uriString)) {
        Assert.fail("Uri string cannot be empty!");
        return uriString;
    }
    // getQueryParameterNames is not exist then cannot iterate on queries
    if (Build.VERSION.SDK_INT < 11) {
        return uriString;
    }

    // Check if uri has valid characters
    // See https://tools.ietf.org/html/rfc3986
    Pattern allowedUrlCharacters = Pattern.compile("([A-Za-z0-9_.~:/?\#\[\]@!$&'()*+,;" +
            "=-]|%[0-9a-fA-F]{2})+");
    Matcher matcher = allowedUrlCharacters.matcher(uriString);
    String validUri = null;
    if (matcher.find()) {
        validUri = matcher.group();
    }
    if (TextUtils.isEmpty(validUri) || uriString.length() == validUri.length()) {
        return uriString;
    }

    // The uriString is not encoded. Then recreate the uri and encode it this time
    Uri uri = Uri.parse(uriString);
    Uri.Builder uriBuilder = new Uri.Builder()
            .scheme(uri.getScheme())
            .authority(uri.getAuthority());
    for (String path : uri.getPathSegments()) {
        uriBuilder.appendPath(path);
    }
    for (String key : uri.getQueryParameterNames()) {
        uriBuilder.appendQueryParameter(key, uri.getQueryParameter(key));
    }
    String correctUrl = uriBuilder.build().toString();
    return correctUrl;
}