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

发布于 2024-08-27 15:09:56 字数 407 浏览 7 评论 0原文

我有一个表示包含空格的 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

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

如何将 myString 解析为 URI 对象?

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

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.

How can i parse myString into a URI object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦断已成空 2024-09-03 15:09:56

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

无论如何,如果您可以确保网址中的空格使其无效,那么您也可以使用 %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 编码

You should in fact URI-encode the "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 String beforehand. The problem really needs to be solved at a higher level. Where does that String come 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.

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:

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:

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). See also Java URL encoding of query string parameters.

梦旅人picnic 2024-09-03 15:09:56
java.net.URLEncoder.encode(finalPartOfString, "utf-8");

这将对字符串进行URL 编码

finalPartOfString 是最后一个斜杠之后的部分 - 在您的情况下,是歌曲的名称,就像它看起来的那样。

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

This will URL-encode the string.

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

烟沫凡尘 2024-09-03 15:09:56

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

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:

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();
}
韶华倾负 2024-09-03 15:09:56
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();
}
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();
}
め七分饶幸 2024-09-03 15:09:56

我写了这个函数:

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_.~:/?\\#\\[\\]@!
amp;'()*+,;" +
            "=-]|%[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;
}

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_.~:/?\\#\\[\\]@!
amp;'()*+,;" +
            "=-]|%[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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文