2009-12-01 96 views
7

我試圖解析以下URI:http://translate.google.com/#zh-CN|en|你如何解析URI這樣在Java中

,但得到這個錯誤信息:

java.net.URISyntaxException: Illegal character in fragment at index 34: http://translate.google.com/#zh-CN|en|你 
     at java.net.URI$Parser.fail(URI.java:2809) 
     at java.net.URI$Parser.checkChars(URI.java:2982) 
     at java.net.URI$Parser.parse(URI.java:3028) 

它有問題,用「|」字符,如果我擺脫了「|」,最後一箇中文字符不會引起任何問題,那麼處理這個問題的正確方法是什麼?

我的方法是這樣的:

public static void displayFileOrUrlInBrowser(String File_Or_Url) 
    { 
    try { Desktop.getDesktop().browse(new URI(File_Or_Url.replace(" ","%20").replace("^","%5E"))); } 
    catch (Exception e) { e.printStackTrace(); } 
    } 

感謝您的答案,但BalusC的解決方案似乎只對URL的一個實例的工作,我的方法需要與任何URL我傳遞給它的,如何工作它會知道將URL分割成兩部分的起點和只編碼第二部分的起點?

回答

13

管道字符是"considered unsafe"用於URL。您可以通過替換|來修復它與其編碼的十六進制等效,這將是「%7C」

但是,替換URL中的單個字符是一個脆弱的解決方案,如果您認爲在任何給定的URL中可能會有相當的可能需要替換的許多不同的字符。你已經在替換空格,插入符號和管道......但括號,重音符號和引號怎麼辦?還是問號和&符號,它們可能是也可能不是URL的有效部分,具體取決於它們的使用方式?

因此,優越的解決方案是使用該語言的工具對網址進行編碼,而不是手動完成。在Java的情況下,使用URLEncoder,根據BalusC對此問題的回答中的示例。

+6

參考:'URLEncoder'(儘管名稱)不應該用於URL編碼。該文檔說:_此類包含將字符串轉換爲application/x-www-form-urlencoded MIME格式的靜態方法._這與URIs/URL使用的編碼不同。 – McDowell 2009-12-01 21:29:48

+0

BalusC的解決方案似乎適用於該實例的url,但我需要該方法適用於所有傳遞給它的url,它將如何知道從什麼起點解析剩餘的url? 這個網址就以下任何一項: www.yahoo.com/abc/xyz http://yahoo.com/abc/123/ yahoo.com/abc/123/... – Frank 2009-12-02 02:56:04

+0

我認爲你需要將網址分割成片段......域,路徑,查詢字符串和片段。該域不應該被編碼。路徑,你將不得不用斜線分割,並對路徑的每一部分進行編碼,然後再將它們放在一起。對於查詢字符串,您需要對每個參數名稱和值進行編碼。你也必須編碼片段。然後,重新組裝URL。 – 2009-12-02 03:25:09

-1

好吧,我發現如何做到這一點,就像這樣:

try { Desktop.getDesktop().browse(new URI(File_Or_Url.replace(" ","%20").replace("^","%5E").replace("|","%7C"))); } 
catch (Exception e) { e.printStackTrace(); } 
+1

使用URLEncoder。 – 2009-12-01 22:21:52

7

你不是最好使用URLEncoder不是選擇性的編碼的東西?

6

您應該使用java.net.URLEncoderUTF-8對查詢進行網址編碼。你不一定需要這樣的正則表達式。你不想有一個正則表達式來涵蓋所有這些數千箇中國字形,你呢? ;)

String query = URLEncoder.encode("zh-CN|en|你", "UTF-8"); 
String url = "http://translate.google.com/#" + query; 
Desktop.getDesktop().browse(new URI(url));  
10

的URLEncoder的解決方案並沒有爲我工作,也許是因爲它編碼只是一切。我正在嘗試使用Apache的HttpGet,並且它會像URL那樣以字符串的形式拋出錯誤。

在我的情況下,正確的做法應該是這個奇怪的代碼:

URL url = new URL(pageURLAsUnescapedString); 
URI uri = new URI(url.getProtocol(), url.getAuthority(), url.getPath(), url.getQuery(), url.getRef()); 

不知怎的url.toURI不相同的方式工作。 URI構造函數有兩種工作方式:如果使用帶有單個String參數的構造函數,則構造函數假裝提供的uri被正確轉義(並因此發生錯誤,這與HttpGet的String構造函數相同);如果您使用多個Strings URI構造函數,那麼該類將非常好地處理一切(並且HttpGet具有另一個接受URI的構造函數)。爲什麼URL.toURI()不這樣做?我不知道...

希望它可以幫助某人,我花了幾個小時才弄明白。

+0

這是錯誤的。如果URL包含一些編碼字符,例如空格「%20」,結果會有不需要的「%2520」。看看示例[這裏](http://ideone.com/7uVSBj)或[我的問題和答案](http://stackoverflow.com/q/13530019/1387438)。 – 2014-03-08 12:18:20

+1

@MarekR我把你最好的兩個答案,並結合他們在http://stackoverflow.com/a/22279061/14731 – Gili 2014-03-09 06:11:37

3

以最好的Federico's answerMarek's answer,你需要做到以下幾點:

URL url = new URL(pageURLAsUnescapedString); 

// URI's constructor expects the path, query string and fragment to be decoded. 
// If we do not decode them, we will end up with double-encoding. 
String path = url.getPath(); 
if (path != null) 
    path = URLDecoder.decode(path, "UTF-8"); 
String query = url.getQuery(); 
if (query != null) 
    query = URLDecoder.decode(query, "UTF-8"); 
String fragment = url.getRef(); 
if (fragment != null) 
    fragment = URLDecoder.decode(fragment, "UTF-8"); 

URI uri = new URI(url.getProtocol(), url.getAuthority(), path, query, fragment); 
+0

'URLDecoder.decode(查詢,「UTF-8」)''也將在參數值解碼符號早 – giorgiga 2015-02-06 09:34:44

0

首先編碼您的網址,請用下面的例子中,再通過URL進入方法

 JSONObject json = new JSONObject(); 
     json.put("name", "vaquar"); 
     json.put("age", "30"); 
     json.put("address", "asasbsa bajsb "); 


     System.out.println("in sslRestClientGETRankColl"+json.toString()); 

     String createdJson=json.toString(); 

     createdJson= URLEncoder.encode(createdJson, "UTF-8"); 

//現在調用方法 displayFileOrUrlInBrowser(createdJson);

public static void displayFileOrUrlInBrowser(String File_Or_Url) 
    { 
    try { Desktop.getDesktop().browse(File_Or_Url); } 
    catch (Exception e) { e.printStackTrace(); } 
    }