【问题标题】:Java - Convert String to valid URI objectJava - 将字符串转换为有效的 URI 对象
【发布时间】:2010-10-09 01:27:26
【问题描述】:

我正在尝试从 String 获取 java.net.URI 对象。该字符串有一些字符需要被它们的百分比转义序列替换。但是当我使用 URLEncoder 用 UTF-8 编码对 String 进行编码时,甚至 / 都被替换为它们的转义序列。

如何从 String 对象中获取有效的编码 URL?

http://www.google.com?q=a b 给出 http%3A%2F%2www.google.com... 而我希望输出为 http://www.google.com?q=a%20b

谁能告诉我如何做到这一点。

我正在尝试在 Android 应用中执行此操作。所以我只能访问有限数量的图书馆。

【问题讨论】:

    标签: java android encoding utf-8


    【解决方案1】:

    你可以试试:org.apache.commons.httpclient.util.URIUtil.encodeQuery in Apache commons-httpclient 项目

    像这样(见URIUtil):

    URIUtil.encodeQuery("http://www.google.com?q=a b")
    

    会变成:

    http://www.google.com?q=a%20b
    

    你当然可以自己做,但是 URI 解析会变得非常混乱......

    【讨论】:

    • 谢谢汉斯。我正在尝试在 Android 应用程序中执行此操作。所以我可以访问数量有限的图书馆。你有什么其他的建议?再次感谢
    • 或许你可以看看 URIUtil 类的源代码(毕竟它是开源的)。我认为可以从该类中提取必要的代码。
    • 指向的项目(Apache commons-httpclient)“现在已经结束生命”。它已被HttpComponents-httpclient 部分取代,但我无法在新 API 中找到等效方法。
    • 我同意 dgiugg。答案已弃用。
    • 对于新版本的 apache 提交似乎不存在 -httpclient
    【解决方案2】:

    您可以使用URI 类的多参数构造函数。来自URIjavadoc:

    多参数构造函数根据它们出现的组件的要求引用非法字符。这些构造函数始终引用百分比字符 ('%')。保留任何其他字符。

    所以如果你使用

    URI uri = new URI("http", "www.google.com?q=a b");
    

    然后你会得到http:www.google.com?q=a%20b,这不太对,但更接近一点。

    如果你知道你的字符串不会有 URL 片段(例如http://example.com/page#anchor),那么你可以使用下面的代码来得到你想要的:

    String s = "http://www.google.com?q=a b";
    String[] parts = s.split(":",2);
    URI uri = new URI(parts[0], parts[1], null);
    

    为了安全起见,您应该扫描字符串中的# 字符,但这应该可以帮助您入门。

    【讨论】:

      【解决方案3】:

      java.net 博客前几天有一个课程可能已经完成了您想要的操作(但它现在已关闭,所以我无法检查)。

      这里的代码可能会被修改为你想要的:

      http://svn.apache.org/repos/asf/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/uri/UriBuilder.java

      这是我从 java.net 想到的一个:https://urlencodedquerystring.dev.java.net/

      【讨论】:

        【解决方案4】:

        如果你不喜欢图书馆,这个怎么样?

        请注意,您不应在整个 URL 上使用此功能,而应在组件上使用此功能...例如只是“a b”组件,因为您构建了 URL - 否则计算机将不知道哪些字符应该具有特殊含义,哪些字符应该具有字面含义。

        /** Converts a string into something you can safely insert into a URL. */
        public static String encodeURIcomponent(String s)
        {
            StringBuilder o = new StringBuilder();
            for (char ch : s.toCharArray()) {
                if (isUnsafe(ch)) {
                    o.append('%');
                    o.append(toHex(ch / 16));
                    o.append(toHex(ch % 16));
                }
                else o.append(ch);
            }
            return o.toString();
        }
        
        private static char toHex(int ch)
        {
            return (char)(ch < 10 ? '0' + ch : 'A' + ch - 10);
        }
        
        private static boolean isUnsafe(char ch)
        {
            if (ch > 128 || ch < 0)
                return true;
            return " %$&+,/:;=?@<>#%".indexOf(ch) >= 0;
        }
        

        【讨论】:

        • 这不起作用(至少在某些情况下)。例如。字符“Š”编码为“%M1”,但应编码为“%C5%A0”。
        • 这也不适用于制表符等字符。如果不匹配 [A-Za-z0-9_-.~],我建议将其更改为不安全。见en.wikipedia.org/wiki/Percent-encoding
        【解决方案5】:

        或者你可以使用这个类:

        http://developer.android.com/reference/java/net/URLEncoder.html

        从 API 级别 1 开始就存在于 Android 中。

        然而,令人讨厌的是,它特别对待空格(用 + 而不是 %20 替换它们)。为了解决这个问题,我们只需使用以下片段:

        URLEncoder.encode(value, "UTF-8").replace("+", "%20");

        【讨论】:

        【解决方案6】:

        Android 一直将 Uri 类作为 SDK 的一部分: http://developer.android.com/reference/android/net/Uri.html

        您可以简单地执行以下操作:

        String requestURL = String.format("http://www.example.com/?a=%s&b=%s", Uri.encode("foo bar"), Uri.encode("100% fubar'd"));
        

        【讨论】:

        • 非常感谢!有时候找到一个简单的 Java 函数需要多长时间,这太荒谬了!
        • 不幸的是,encode() 方法在尝试对正斜杠(“/”)进行编码时很糟糕。我只是使用了一个普通的旧 String.replace() 来完成工作。那很蹩脚... searchQuery.replace("/", "%2f");
        【解决方案7】:

        我的一个项目在从字符串创建 URI 对象时遇到了类似的问题。我也找不到任何干净的解决方案。这是我想出的:

        public static URI encodeURL(String url) throws MalformedURLException, URISyntaxException  
        {
            URI uriFormatted = null; 
        
            URL urlLink = new URL(url);
            uriFormatted = new URI("http", urlLink.getHost(), urlLink.getPath(), urlLink.getQuery(), urlLink.getRef());
        
            return uriFormatted;
        }
        

        如果需要,您可以使用以下 URI 构造函数来指定端口:

        URI uri = new URI(scheme, userInfo, host, port, path, query, fragment);
        

        【讨论】:

        • 不处理转换问号(我尝试使用 URL:http://www.google.com/Do you like Spam? 并且它处理了空格,但不是最后的问号)
        • @kentcdodds 这是因为在这种情况下问号是合法的。我敢肯定,如果你再添加一个,它就会被转换
        【解决方案8】:

        我将在这里添加一个针对 Android 用户的建议。您可以这样做,以避免必须获取任何外部库。此外,上述某些答案中建议的所有搜索/替换字符解决方案都是危险的,应该避免。

        试试这个:

        String urlStr = "http://abc.dev.domain.com/0007AC/ads/800x480 15sec h.264.mp4";
        URL url = new URL(urlStr);
        URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
        url = uri.toURL();
        

        您可以看到,在这个特定的 URL 中,我需要对这些空格进行编码,以便可以将其用于请求。

        这利用了 Android 类中提供给您的几个功能。首先,URL 类可以将 url 分解为其适当的组件,因此您无需进行任何字符串搜索/替换工作。其次,当您通过组件而不是从单个字符串构造 URI 时,这种方法利用了 URI 类特性正确转义组件。

        这种方法的美妙之处在于,您可以获取任何有效的 url 字符串并使其工作,而无需自己掌握任何特殊知识。

        【讨论】:

          【解决方案9】:

          我试过用

          String converted = URLDecoder.decode("toconvert","UTF-8");
          

          我希望这就是你真正想要的?

          【讨论】:

          • 这是我一直在寻找的答案,不需要依赖外部库。
          • 不,这是错误的答案。 URLDecoder.decode("to convert","UTF-8") 返回“转换”,URLDecoder.decode("to%20convert","UTF-8") 返回“转换”。所以这与问题的要求相反。
          【解决方案10】:

          即使这是一个已经接受答案的旧帖子,我也会发布我的替代答案,因为它适用于当前问题,而且似乎没有人提到这种方法。

          使用 java.net.URI 库:

          URI uri = URI.create(URLString);
          

          如果你想要一个与之对应的 URL 格式的字符串:

          String validURLString = uri.toASCIIString();
          

          与许多其他方法(例如 java.net.URLEncoder)不同,此方法仅替换不安全的 ASCII 字符(例如 çé...)。


          在上面的例子中,如果URLString是下面的String

          "http://www.domain.com/façon+word"
          

          生成的validURLString 将是:

          "http://www.domain.com/fa%C3%A7on+word"
          

          这是一个格式正确的 URL。

          【讨论】:

          • 你的答案就是我要找的答案,由于各种原因我无法提取参数,这是唯一真正有效的方法。
          • 而且每个人在处理异常时也应该看看文档developer.android.com/reference/java/net/…
          • 这似乎不能转换引号?即'"
          • @behelit 没错,刚刚检查过。但是,' is a safe character。但是" 引发了异常!与 java.net.URL 相同。
          【解决方案11】:

          我最终使用了 httpclient-4.3.6:

          import org.apache.http.client.utils.URIBuilder;
          public static void main (String [] args) {
              URIBuilder uri = new URIBuilder();
              uri.setScheme("http")
              .setHost("www.example.com")
              .setPath("/somepage.php")
              .setParameter("username", "Hello Günter")
              .setParameter("p1", "parameter 1");
              System.out.println(uri.toString());
          }
          

          输出将是:

          http://www.example.com/somepage.php?username=Hello+G%C3%BCnter&p1=paramter+1

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-04-12
            • 2011-08-30
            • 2015-01-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-17
            相关资源
            最近更新 更多