当URL中存在不规范字符时,如何将其转换为URI?

6
我有一个包含不安全字符 (RFC 2396)的路径的URL对象,其中在我的情况下是 "|" (管道) 字符。现在我需要安全地将其转换为URI,但URL.toURI()会抛出异常。
我阅读了URL文档,但这部分对我来说很困惑:

URL类本身不根据RFC2396中定义的转义机制对任何URL组件进行编码或解码。调用者有责任在调用URL之前对需要进行转义的任何字段进行编码,以及解码从URL返回的任何已转义字段。此外,因为URL没有URL转义的知识,它不承认同一URL的编码或解码形式之间的等价性。

那么我该怎么做呢?在转换过程中要对这些字符进行编码的模式是什么?我需要创建URL对象的编码副本吗?
3个回答

3
好的,我来翻译一下:

好的,我想到了这样的东西:

URI uri = new URI(url.getProtocol(), 
                  null /*userInfo*/,
                  url.getHost(), 
                  url.getPort(), 
                  (url.getPath()==null)?null:URLDecoder.decode(url.getPath(), "UTF-8"),
                  (url.getQuery()==null)?null:URLDecoder.decode(url.getQuery(), "UTF-8"),
                  null /*fragment*/);

看起来它能工作,这里有一个例子。有人可以确认这是正确的解决方案吗?

编辑最初的解决方案在查询时存在一些问题,所以我已经修复了它。


是的,你是对的。我注意到一段时间前在 ideone.com(见第一个链接),我纠正了我的解决方案,并添加了额外的测试用例来揭示这个问题。我会检查你的解决方案,它看起来更好。 - Marek R
请参见 https://dev59.com/Q0rSa4cB1Zd3GeqPXpmW#4960779 获取更好/更干净的解决方案(例如,他保留了片段)。 - Gili
@Gili 我不得不回忆起我为什么添加了decode,问题在这里变得明显(http://ideone.com/7uVSBj)。看一下包含编码字符(如“%20”)的URL的“uri.toString”结果的示例 - 编码已损坏。 - Marek R
@Gili 如果你看之前的评论,你会注意到我犯了同样的错误 :)。 - Marek R
你关于需要解码的说法是正确的,但是你关于传递空的userInfo和fragment的说法是错误的。正确的答案是在https://dev59.com/Q0rSa4cB1Zd3GeqPXpmW#4960779中添加解码。 - Gili
显示剩余4条评论

1
HTTPClient 4有一个相关对象,即org.apache.http.client.utils.URIBuilder:
           URIBuilder builder = 
            new URIBuilder()
        .setScheme(url.getProtocol())
        .setHost(url.getHost())
        .setPort(url.getPort())
        .setUserInfo(url.getUserInfo())
        .setPath(url.getPath())
        .setQuery(url.getQuery());
    URI uri = builder.build();
    return uri;

1

使用URL编码?

从您的示例中,您目前拥有:

URL url = new URL("http", "google.com", 8080, "/crapy|path with-unwise_characters.jpg");

相反,我会使用:

String path = "/crapy|path with-unwise_characters.jpg"
URL url = new URL("http", "google.com", 8080, URLEncoder.encode(path, "UTF-8"));

这应该能够按照标准的 URL 编码处理并处理路径中的所有不良字符。


这是一个可以接受的解决方案,但我的主要目标是将其转换为URI,因此我的解决方案更直接,特别是我不创建URL,它来自第三方代码。 - Marek R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接