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

时间:2010-04-07 14:21:28

标签: java android url uri httprequest

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

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

它给了我

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

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

如何将myString解析为URI个对象?

5 个答案:

答案 0 :(得分:120)

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

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

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

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

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

请注意URLEncoder对于任务是不可接受的,因为它旨在根据application/x-www-form-urlencoded规则(在HTML表单中使用)对查询字符串参数名称/值进行编码。另请参阅Java URL encoding of query string parameters

答案 1 :(得分:19)

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

这将是URL-encode字符串。

finalPartOfString是最后一次斜线之后的部分 - 就你的情况而言,就是这首歌的名字。

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

我写了这个函数:

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