Android: Как разобрать строку URL с пробелами для объекта 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 это позиция первого пробела в строке адреса.
как я могу распарсить myStringна
5 ответов:
вы должны на самом деле URI-encode "неправильные" символы. Поскольку строка фактически содержит полный URL-адрес, ее трудно правильно кодировать URI. Вы не знаете, какие косые черты
/должны быть приняты во внимание, а какие нет. Вы не можете предсказать, что на сырье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 параметров строки запроса.
java.net.URLEncoder.encode(finalPartOfString, "utf-8");Это URL-encode строку.
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; }
Comments