简体   繁体   English

Android:如何解析带有空格的URL String到URI对象?

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

I have a string representing an URL containing spaces and want to convert it to an URI object. 我有一个字符串表示包含空格的URL,并希望将其转换为URI对象。 If I simply try to create it via 如果我只是尝试通过它创建它

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 X is the position of the first space in the URL string. 其中索引X是URL字符串中第一个空格的位置。

How can i parse myString into a URI object? 如何将myString解析为URI对象?

You should in fact URI-encode the "invalid" characters. 实际上,您应该 “无效”字符进行URI编码 Since the string actually contains the complete URL, it's hard to properly URI-encode it. 由于字符串实际上包含完整的URL,因此很难对其进行正确的URI编码。 You don't know which slashes / should be taken into account and which not. 你不知道哪些斜线/应该考虑哪些斜线,哪些斜线不应该考虑。 You cannot predict that on a raw String beforehand. 您无法预先在原始String上预测。 The problem really needs to be solved at a higher level. 问题确实需要在更高层次上解决。 Where does that String come from? 这个String来自哪里? 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. 验证它并显示错误,让用户解决自己。

At any way, if you can ensure that it are only the 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 only the part after the last slash which needs to be URI-encoded, then you can also just do so with help of android.net.Uri utility 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 URLEncoder is insuitable for the task as it's designed to encode query string parameter names/values as per application/x-www-form-urlencoded rules (as used in HTML forms). 请注意URLEncoder对于任务是不可或缺的,因为它被设计为根据application/x-www-form-urlencoded规则(在HTML表单中使用)对查询字符串参数名称/值进行编码。 See also Java URL encoding of query string parameters . 另请参阅查询字符串参数的Java URL编码

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

This will URL-encode the string. 这将对字符串进行URL编码

finalPartOfString is the part after the last slash - in your case, the name of the song, as it seems. finalPartOfString是最后一个斜杠之后的部分 - 在你的情况下,是歌曲的名字,看起来如此。

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM