2010-04-07 11 views
56

Mam ciąg reprezentujący adres URL zawierający spacje i chcę go przekonwertować na obiekt URI. Jeśli jest proste spróbuj zrobićAndroid: howto parsować ciąg adresu URL ze spacjami do obiektu URI?

String myString = "http://myhost.com/media/mp3s/9/Agenda of swine - 13. Persecution Ascension_ leave nothing standing.mp3"; 
URI myUri = new URI(myString); 

daje mi

java.net.URISyntaxException: Illegal character in path at index X 

gdzie indeks X jest pozycja pierwszego miejsca w ciągu URL.

Jak przeanalizować obiekt myString na obiekt ?

Odpowiedz

110

Powinieneś w rzeczywistości URI-encode "nieważne" znaki. Ponieważ ciąg faktycznie zawiera pełny adres URL, trudno jest go poprawnie kodować URI. Nie wiesz, które ukośniki należy wziąć pod uwagę, a które nie. Nie można tego wcześniej przewidzieć na surowym String. Problem naprawdę musi zostać rozwiązany na wyższym poziomie. Skąd pochodzi String? Czy to jest na stałe? Następnie zmień to odpowiednio. Czy przychodzi jako dane wejściowe użytkownika? Sprawdź poprawność i pokaż błąd, pozwól użytkownikowi rozwiązać problem.

w jakikolwiek sposób, jeśli można zapewnić, że to są tylko przestrzenie w URL, który sprawia, że ​​jest nieważny, to można też po prostu zrobić łańcuch po ciąg zastąpić %20:

URI uri = new URI(string.replace(" ", "%20")); 

lub jeśli można zapewnić, że to tylko część po ostatnim ukośniku który musi być zakodowany URI, to można też po prostu zrobić z pomocą klasy android.net.Uri użytkowy:

int pos = string.lastIndexOf('/') + 1; 
URI uri = new URI(string.substring(0, pos) + Uri.encode(string.substring(pos))); 

Należy zauważyć, że URLEncoder nie nadaje się do zadania, ponieważ jest przeznaczony do kodowania nazw/wartości parametrów ciągów zapytań zgodnie z regułami application/x-www-form-urlencoded (używanymi w formularzach HTML). Zobacz także Java URL encoding of query string parameters.

+1

Zamieniając spacje na '% 20' wykonaj sztuczkę. THX – Mannaz

+4

@Mannaz - zachowaj ostrożność, gdy w nazwie utworu pojawi się inny "nieważny" symbol. – Bozho

+0

@BalusC wypróbowałem URLEncoder.encode ("ciąg zapytania", "UTF-8"); powraca z symbolem + takim jak "zapytanie + ciąg", w którym się spodziewam "% 20". Więc użyłem string.replace z zakodowanymi na stałe wartościami. Rozwiązano problem. Dzięki za informację. Czy jest jakiś inny sposób kodowania zamiast ręcznej zamiany ...? – praveenb

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

Będzie URL-encode ciąg.

finalPartOfString to część po ostatnim slashu - w Twoim przypadku nazwa piosenki, jak się wydaje.

+2

Spowoduje to również urlenie okrężnicy i ukośniki, które sprawiają, że adres URL jest nadal nieważny. Zasadniczo wystarczy, aby spenkodować spacje, aby było prawidłowe. – BalusC

+0

@BalusC, dzięki, dodałem aktualizację. – Bozho

+0

Ok, to dostaje mnie przez 'URISyntaxException', ale teraz dostaję 404 z serwera. Adres URL, który otrzymuję, to 'http: //myhost.com/media/mp3s/9/Agenda+swine + - + 13. + Prześladowanie + Wniebowstąpienie_ + pozostawienie + nic + Standing.mp3'. Używam identyfikatora URI w 'org.apache.http.client.methods.HttpGet.Prośba HttpGet. Jakieś pomysły? – Mannaz

1

Aby obsłużyć przestrzenie, @ i inne znaki niebezpiecznych w dowolnych miejscach na ścieżkę URL, Korzystanie Uri.Builder w połączeniu z lokalnego wystąpienie URL jak opisałem 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(); 
} 
0
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(); 
} 
+0

dlaczego negatywne oznakowanie? – siddmuk2005

+0

, ponieważ nie odpowiada na pytanie. – MetaFight

+1

Podałem to, aby usunąć spację z adresu URL, aby rozwiązać mój problem, ponieważ podczas odczytywania lokalizacji pliku punkty FileInputStream mają wartość NULL, a podczas czytania z wartością null będzie to rzutować bity wyjątków przy użyciu identyfikatora URI, ale nie otrzymałem problemu. – siddmuk2005

0

Napisałem tę funkcję:

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; 
} 
Powiązane problemy