Android: howto parse URL String с пробелами для объекта URI?
У меня есть строка, представляющая URL-адрес, содержащий пробелы, и вы хотите преобразовать его в объект URI. Если просто попробуйте сделать
String myString = "http://myhost.com/media/mp3s/9/Agenda of swine - 13. Persecution Ascension_ leave nothing standing.mp3";
URI myUri = new URI(myString);
это дает мне
java.net.URISyntaxException: Illegal character in path at index X
где index X
- это позиция первого пробела в строке URL.
Как я могу разобрать myString
в объект URI
?
Ответы
Ответ 1
На самом деле вы должны кодировать URI "недопустимые" символы. Поскольку строка фактически содержит полный URL-адрес, трудно правильно кодировать URI. Вы не знаете, какие косые черты /
должны быть приняты во внимание, а какие нет. Вы не можете заранее предсказать это на raw 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-формах). См. Также Кодировка URL-адресов URL-адресов строки запроса.
Ответ 2
java.net.URLEncoder.encode(finalPartOfString, "utf-8");
Это будет URL-кодировать строку.
finalPartOfString
- это часть после последней косой черты - в вашем случае, название песни, как кажется.
Ответ 3
Чтобы обрабатывать пробелы, @и другие небезопасные символы в произвольных местах в 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();
}
Ответ 4
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();
}
Ответ 5
Я написал эту функцию:
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;
}