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 

Где индекс X является позицией первого пространства в строке URL.

Как я могу разобрать myString в объект URI ?

Solutions Collecting From Web of "Android: howto parse URL String с пробелами для URI-объекта?"

Вы должны на самом деле кодировать URI «недопустимые» символы. Поскольку строка фактически содержит полный URL-адрес, трудно правильно кодировать URI. Вы не знаете, какие косые черты / должны быть приняты во внимание, а какие нет. Вы не можете заранее предсказать это на необработанном Строке. Проблема действительно должна быть решена на более высоком уровне. Откуда эта 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-адресов строки запроса Java .

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

Это URL-кодирует строку.

finalPartOfString – это часть после последней косой черты – в вашем случае, название песни, как кажется.

Чтобы обрабатывать пробелы, @ и другие небезопасные символы в произвольных местоположениях в 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(); } 
 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(); } 

Я написал эту функцию:

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