2010-04-07 35 views
56

我有一個字符串表示一個包含空格的URL,並希望將其轉換爲一個URI對象。如果是嘗試簡單的事情Android:howto解析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字符串的第一個空間的位置。

如何可以解析myStringURI對象?

回答

110

你其實應該URI-encode「無效」字。由於字符串實際上包含完整的URL,因此很難對其進行正確的URI編碼。您不知道應該將哪些斜槓/考慮在內,哪些不適用。您無法事先預測原始String。這個問題真的需要在更高的層面上解決。 String從哪裏來?它是否被硬編碼?然後,只需相應地改變它。它是否以用戶輸入的形式出現?驗證並顯示錯誤,讓用戶自行解決。

在任何方式,如果你能保證它是只有在URL中的空間,這使得它無效,那麼你也可以只是做一個字符串逐串%20替換:

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

int pos = string.lastIndexOf('/') + 1; 
URI uri = new URI(string.substring(0, pos) + Uri.encode(string.substring(pos))); 
:或者,如果你能保證它的唯一 其中需要被URI編碼的最後一個斜線之後的部分,那麼你也可以只是 android.net.Uri實用類的幫助,這樣做

請注意URLEncoder是不適合的任務,因爲它被設計爲按照application/x-www-form-urlencoded規則(如在HTML表單中使用的)對查詢字符串參數名稱/值進行編碼。另見Java URL encoding of query string parameters

+1

用'%20'代替空格就是訣竅。 THX – Mannaz 2010-04-07 15:14:38

+4

@Mannaz - 當歌曲名稱中出現另一個「無效」符號時要小心。 – Bozho 2010-04-07 19:31:02

+0

@BalusC我試過URLEncoder.encode(「查詢字符串」,「UTF-8」);它返回+符號像這樣「查詢+字符串」,我期待「%20」。所以我用string.replace和硬編碼的值。解決了這個問題。謝謝(你的)信息。有沒有其他的途徑來編碼,而不是手動替換..? – praveenb 2012-04-05 11:20:56

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

這將是URL-encode的字符串。

finalPartOfString是最後一個斜線之後的部分 - 在你的情況下,歌曲的名字,因爲它似乎。

+2

它也將urlencode冒號和斜線,這將導致url仍然無效。他基本上只需要對空格進行urlencode以使其有效。 – BalusC 2010-04-07 14:26:32

+0

@BalusC,謝謝,我添加了一個更新。 – Bozho 2010-04-07 14:29:25

+0

好了,這讓我在'URISyntaxException'但現在我從服務器獲取404。 的網址我得到的是通過'http://myhost.com/media/mp3s/9/Agenda+of+swine + - + 13 +迫害+ Ascension_ +留下+什麼+ standing.mp3'。 我使用URI在'org.apache.http.client.methods.HttpGet。HttpGet'請求。有任何想法嗎? – Mannaz 2010-04-07 14:44:16

1

要處理空格,@,並在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(); 
} 
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

負號爲什麼是負號? – siddmuk2005 2014-08-04 10:26:45

+0

,因爲這不回答這個問題。 – MetaFight 2014-09-02 15:56:09

+1

我已經給這個從URL中刪除的空間,所以它解決了我的問題,因爲當閱讀文件位置FileInputStream指向空,而閱讀與空它會拋出異常BU使用URI我沒有得到問題。 – siddmuk2005 2014-09-04 06:07:44

0

我寫了這個函數:

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