2010-04-07 38 views
56

Tôi có một chuỗi đại diện cho một URL có chứa dấu cách và muốn chuyển đổi nó thành một đối tượng URI. Nếu là đơn giản cố gắng để làmAndroid: cách phân tích cú pháp chuỗi URL với khoảng trắng thành đối tượng URI?

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

nó mang lại cho tôi

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

nơi index X là vị trí của không gian đầu tiên trong chuỗi URL.

Tôi làm cách nào để phân tích cú pháp myString thành đối tượng URI?

Trả lời

110

Bạn nên thực tế là URI-encode ký tự "không hợp lệ". Vì chuỗi thực sự chứa URL hoàn chỉnh, thật khó để mã hóa URI đúng cách. Bạn không biết những dấu gạch chéo / nên được đưa vào tài khoản và không. Bạn không thể dự đoán trước đó trên String thô. Vấn đề thực sự cần phải được giải quyết ở cấp độ cao hơn. Trường hợp đó String đến từ đâu? Nó có được mã hóa không? Sau đó, chỉ cần thay đổi nó cho mình cho phù hợp. Liệu nó có phải là đầu vào của người dùng không? Xác nhận nó và hiển thị lỗi, cho phép người dùng tự giải quyết.

Tại bất kỳ cách nào, nếu bạn có thể đảm bảo rằng nó chỉ các khoảng trắng trong URL mà làm cho nó không hợp lệ, sau đó bạn cũng có thể chỉ cần làm một chuỗi theo chuỗi thay thế với %20:

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

hoặc nếu bạn có thể đảm bảo rằng nó chỉ phần sau dấu gạch chéo cuối cùng mà cần phải được URI mã hóa, sau đó bạn có thể cũng chỉ làm như vậy với sự giúp đỡ của lớp android.net.Uri tiện ích:

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

Lưu ý rằng URLEncoder không phù hợp với tác vụ vì nó được thiết kế để mã hóa các tên/giá trị tham số chuỗi truy vấn theo các quy tắc application/x-www-form-urlencoded (như được sử dụng trong biểu mẫu HTML). Xem thêm Java URL encoding of query string parameters.

+1

Thay thế các khoảng trống bằng '% 20'. THX – Mannaz

+4

@Mannaz - chỉ cần cẩn thận khi một biểu tượng "không hợp lệ" khác xuất hiện trong tên bài hát. – Bozho

+0

@BalusC tôi đã thử URLEncoder.encode ("chuỗi truy vấn", "UTF-8"); nó quay trở lại với biểu tượng + như "truy vấn + chuỗi" này, nơi im mong đợi "% 20". Vì vậy, tôi đã sử dụng string.replace với hardcoded các giá trị. Giải quyết vấn đề. Cảm ơn bạn về thông tin. Có cách nào khác để mã hóa thay vì thay thế thủ công ..? – praveenb

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

Điều này sẽ URL-encode chuỗi.

finalPartOfString là một phần sau dấu gạch chéo cuối cùng - trong trường hợp của bạn, tên của bài hát, có vẻ như.

+2

Nó cũng sẽ urlencode dấu hai chấm và dấu gạch chéo sẽ làm cho url vẫn không hợp lệ. Ông về cơ bản chỉ cần urlencode các không gian để có được nó hợp lệ. – BalusC

+0

@BalusC, cảm ơn, tôi đã thêm bản cập nhật. – Bozho

+0

Ok, điều này được tôi bởi 'URISyntaxException' nhưng bây giờ tôi nhận được một 404 từ máy chủ. Url tôi nhận được là 'http: //myhost.com/media/mp3s/9/Agenda+of+swine + - + 13. + Bắt buộc + Ascension_ + rời + không có gì + đứng.mp3'. Tôi sử dụng URI trong một 'org.apache.http.client.methods.HttpGet.HttpGet' Yêu cầu. Bất kỳ ý tưởng? – Mannaz

1

Xử lý không gian, @, và các nhân vật không an toàn khác tại các địa điểm tùy ý trong đường dẫn url, Sử dụng Uri.Builder kết hợp với một trường hợp địa phương của URL như tôi đã mô tả 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

tại sao đánh dấu tiêu cực? – siddmuk2005

+0

vì điều này không trả lời được câu hỏi. – MetaFight

+1

Tôi đã đưa ra điều này để loại bỏ không gian từ URL để giải quyết vấn đề của tôi bởi vì trong khi đọc vị trí tệp FileInputStream trỏ tới null và trong khi đọc với null nó sẽ ném Exception bu sử dụng URI tôi đã không nhận được vấn đề. – siddmuk2005

0

Tôi đã viết chức năng này:

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; 
} 
Các vấn đề liên quan