2011-01-29 80 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; 
相关问题