java 当 URL 包含“]”时,使用 URL.getPort() 提取端口号时出现问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4839447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:16:14  来源:igfitidea点击:

Problem extracting port number with URL.getPort() when URL contains "]"

javaandroidurl

提问by Mike Lowery

I'm using java.net.URL.getPort() to extract the port number from a URL. Most of the time this works great. However, when the URL contains a right bracket character "]" it fails:

我正在使用 java.net.URL.getPort() 从 URL 中提取端口号。大多数时候这很好用。但是,当 URL 包含右括号字符“]”时,它会失败:

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

But if the URL contains "]" I get:

但如果 URL 包含“]”,我会得到:

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

What am I doing wrong?

我究竟做错了什么?

EDIT #1: As a test, I pasted this same code into a non-Android Java app and the port number was correctly returned, so this appears to be an anomaly with the Android SDK.

编辑 #1:作为测试,我将此相同的代码粘贴到非 Android Java 应用程序中,并且正确返回了端口号,因此这似乎是 Android SDK 的异常情况。

回答by Jonas

If your URL contains some symbols that are not valid in URLs, you have to use an URL-encoded String. They way to do it in Java seem to be by using URI.

如果您的 URL 包含一些在 URL 中无效的符号,则必须使用 URL 编码的字符串。他们在 Java 中的实现方式似乎是使用URI.

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

If you already has an URL string:

如果您已经有一个 URL 字符串:

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

Then this works for me:

然后这对我有用:

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

But then again I'm using url.getPort()that you said didn't work. But when I'm testing on Java 6 now. new URL("http://abc.com:123/abc].mp3").getPort();actually works for me, maybe it's just on Android it doesn't work? In case it doesn't work I think it's best to use a third party library for this. Apache Http Client that is included in Android seem to have some extra functionality for URLs: see org.apache.http.client.utils

但话又说回来,我正在使用url.getPort()你说的不起作用。但是当我现在在 Java 6 上进行测试时。new URL("http://abc.com:123/abc].mp3").getPort();实际上对我有用,也许它只是在 Android 上不起作用?如果它不起作用,我认为最好为此使用第三方库。Android 中包含的 Apache Http Client 似乎具有一些额外的 URL 功能:请参阅org.apache.http.client.utils

See also HTTP URL Address Encoding in Java

另请参阅Java 中的 HTTP URL 地址编码

回答by McDowell

"http://abc.com:123/abc].mp3"

]is not allowed in the path part of a URI, so this is not a URL. However, you can modify the regular expression in the specto get this information:

]不允许出现在 URI 的路径部分,因此这不是 URL。但是,您可以修改规范中正则表达式以获取此信息:

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

Despite the name, URLEncoderdoesn't encode URLs. It should only be used to encode parameters in the query part when the server is expecting application/x-www-form-urlencodedencoded data. The URIand URLclasses behave as documented - they aren't going to help you here.

尽管有名称,URLEncoder但不编码 URL。当服务器需要application/x-www-form-urlencoded编码数据时,它应该只用于对查询部分中的参数进行编码。在URIURL类表现为记录-他们是不会帮助你在这里。

回答by dave.c

According to RFC1738the ]character is unsafe:

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

Other characters are unsafe because gateways and other transport agents are known to sometimes modify such characters. These characters are "{", "}", "|", "\", "^", "~", "[", "]", and "`".

Thus, only alphanumerics, the special characters "$-_.+!*'(),", and reserved characters used for their reserved purposes may be used unencoded within a URL.

其他字符是不安全的,因为网关和其他传输代理有时会修改这些字符。这些字符是“{”、“}”、“|”、“\”、“^”、“~”、“[”、“]”和“`”。

因此,只有字母数字、特殊字符“$-_.+!*'(),”和用于其保留目的的保留字符可以在 URL 中未编码地使用。

You should encode either the individual character that you want to add, or run the whole string through a URL encoder. Try this:

您应该对要添加的单个字符进行编码,或者通过 URL 编码器运行整个字符串。试试这个:

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

回答by user207421

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

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

回答by Rami Jaamour

Here is a simpler way to extract port from URLs that may be different from HTTP, e.g. JNDI connection URLs:

这是从可能与 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;