2011-01-29 81 views
4

我正在使用java.net.URL.getPort()從URL中提取端口號。大多數情況下,這很有效。然而,當URL包含一個右括號字符 「]」 失敗:當URL包含「]」時,使用URL.getPort()提取端口號時出現問題

new URL("http://abc.com:123/abc.mp3").getPort(); 
returns: (int) 123 

但如果URL中包含 「]」 我得到:

new URL("http://abc.com:123/abc].mp3").getPort(); 
returns: (int) -1 

我在做什麼錯?編輯#1:作爲測試,我將這個相同的代碼粘貼到非Android Java應用程序中,並且端口號被正確地返回,所以這似乎是Android SDK的一個異常。

回答

4

如果您的URL包含一些在URL中無效的符號,則必須使用URL編碼的字符串。他們用Java來做的方式似乎是使用URI

new URI("http", null, "abc.com", 123, "abc].mp3", null, null).toURL().getPort(); 

如果你已經有一個URL字符串:

URL url = new URL("http://abc.com:123/abc].mp3"); 

那麼這個工作對我來說:

new URI(
    url.getProtocol(), 
    null, 
    url.getHost(), 
    url.getPort(), 
    url.getPath(), 
    null, 
    null); 

不過話又說回來,我使用url.getPort()你說沒有工作。但是現在我正在測試Java 6。 new URL("http://abc.com:123/abc].mp3").getPort();實際上適用於我,也許它只是在Android上不起作用?如果它不起作用,我認爲最好爲此使用第三方庫。包含在Android的Apache的HTTP客戶端似乎有網址的一些額外的功能:看org.apache.http.client.utils

參見HTTP URL Address Encoding in Java

+2

換句話說,方括號不是有效的URL:http://www.ietf.org/rfc/rfc3986.txt – CommonsWare 2011-01-29 21:19:11

+1

這會導致被拋出,因爲java.net.MalformedURLException一切都被編碼,而不僅僅是無效的字符。 – 2011-01-29 21:44:07

+1

@DiskCrasher:你說得對。我更新並使用了「URI」類。現在它工作,但API是笨拙的:( – Jonas 2011-01-30 00:24:27

1

根據RFC1738]字符是不安全的:

其他字符是不安全的,因爲已知網關和其他傳輸代理有時修改這些字符。這些字符是「{」,「}」,「|」,「\」,「^」,「〜」,「[」,「]」和「`」。因此,只有字母數字,特殊字符「$ -_。+!*()」以及用於保留目的的保留字符可以在URL內未經編碼的情況下使用。

您應該對要添加的單個字符進行編碼,或者通過URL編碼器運行整個字符串。試試這個:

new URL("http://abc.com:123/abc%5D.mp3").getPort(); 
2
"http://abc.com:123/abc].mp3" 

]不是在URI路徑部分不允許的,所以這不是一個URL。但是,您可以修改regular expression in the spec得到這個信息:

//TODO: import java.util.regex.*; 
    String expr = "^(([^:/?#]+):)?(//([^:/?#]*):([\\d]*))?"; 
    Matcher matcher = Pattern.compile(expr) 
          .matcher("http://abc.com:123/abc].mp3"); 
    if (matcher.find()) { 
     String port = matcher.group(5); 
     System.out.println(port); 
    } 

儘管名字,URLEncoder不編碼的URL。當服務器期待application/x-www-form-urlencoded編碼數據時,它只能用於編碼查詢部分的參數。 URIURL類的行爲與記錄 - 他們不會幫你在這裏。

0

String encodedURL = new URI(「http」,null,「//abc.com:8080/abc[d].jpg」,null,null).toASCIIString();

0

這是一種更簡單的方法來從可能與HTTP不同的URL中提取端口。 JNDI連接URL:

int port = 80; // assumption of default port in the URL 
Pattern p = Pattern.compile(":\\d+"); // look for the first occurrence of colon followed by a number 
Matcher matcher = p.matcher(urlSrtr); 
if (matcher.find()) { 
    String portStrWithColon = matcher.group(); 
    if (portStrWithColon.length() > 1) { 
     String portStr = portStrWithColon.substring(1); 
     try { 
      port = Integer.parseInt(portStr); 
     } catch (NumberFormatException e) { 
      // handle 
     } 
    } 
} 
return port; 
相關問題