web-dev-qa-db-ja.com

Android:スペースを含むURL文字列をURIオブジェクトに解析する方法は?

スペースを含む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文字列の最初のスペースの位置です。

myStringURIオブジェクトに解析するにはどうすればよいですか?

61
whlk

実際には、 RI-encode 「無効な」文字である必要があります。文字列には実際には完全なURLが含まれているため、適切にURIエンコードすることは困難です。どのスラッシュ/を考慮する必要があるか、またどのスラッシュを考慮しないかはわかりません。事前にStringでそれを予測することはできません。問題は本当に高いレベルで解決する必要があります。 Stringはどこから来たのですか?ハードコーディングされていますか?それに応じて自分で変更してください。ユーザー入力として入っていますか?検証してエラーを表示し、ユーザーが自分で解決できるようにします。

いずれにしても、それが無効になるURLのスペースがonlyだけであることを確認できる場合は、string-by-文字列を%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エンコード も参照してください。

120
BalusC
Java.net.URLEncoder.encode(finalPartOfString, "utf-8");

これは RL-encode 文字列です。

finalPartOfStringは最後のスラッシュの後の部分です-あなたの場合は、曲の名前です。

19
Bozho
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();
}
2
siddmuk2005

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

この関数を書きました:

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