uri和url有啥关系和区别?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uri和url有啥关系和区别?相关的知识,希望对你有一定的参考价值。

RT`

参考技术A URL与URI之间的区别在于URI是以一种抽象的,高层次概念定义统一资源标识,而URL则是具体的资源标识的方式。URL是一种URI。另外URI和URL之间的格式不同:URL的格式一般由下列三部分组成:第一部分是协议(或称为服务方式);第二部分是存有该资源的主机IP地址(有时也包括端口号);第三部分是主机资源的具体地址。URI一般由三部分组成:访问资源的命名机制;存放资源的主机名;资源自身的名称,由路径表示。在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的,schema(protocol)必须被指定。 参考技术B uri是通用资源标志符
url是统一资源定位符
例如:http://baike.baidu.com/view/160675.html
url是:http://baike.baidu.com/view/160675.html
uri是:/view/160675.html

参考资料:据我了解

参考技术C URI、URL和URN区别:
URI :Uniform Resource Identifier,统一资源标识符;
URL:Uniform Resource Locator,统一资源定位符;
其中,URL是URI的子集。

EscapeUriString 和 EscapeDataString 有啥区别?

【中文标题】EscapeUriString 和 EscapeDataString 有啥区别?【英文标题】:What's the difference between EscapeUriString and EscapeDataString?EscapeUriString 和 EscapeDataString 有什么区别? 【发布时间】:2011-05-22 17:57:38 【问题描述】:

如果只处理url编码,我应该使用EscapeUriString?

【问题讨论】:

始终使用Uri.EscapeDataString() 转义每个单独的,如@Livven 的回答中所述。使用其他方法时,系统根本没有足够的信息来为每个可能的输入产生预期的结果。 【参考方案1】:

始终使用EscapeDataString(有关原因的更多信息,请参阅下面的Livven's answer)

编辑:删除了两者在编码上有何不同的死链接

【讨论】:

我不确定该链接是否提供了更多信息,因为它是关于取消转义而不是转义。 基本是一样的区别。如果你真的阅读了这篇文章,中间有一个表格,它实际上转义(不是 unescapes)以显示差异(也与 URLEncode 比较)。 我仍然不清楚——如果我没有转义整个 URI 而只是其中的一部分——(即查询字符串参数的 data)怎么办? ?我是在转义 URI 的数据,还是 EscapeDataString 暗示完全不同的东西? ... 做了一些测试,看起来我想要 EscapeDataString 作为 URI 参数。我用字符串“I heart C++”进行了测试,EscapeUriString 没有对“+”字符进行编码,它只是保持原样,EscapeDataString 正确地将它们转换为“%2B”。 这是一个糟糕的答案。你永远不应该使用 EscapeUriString,它没有任何意义。请参阅下面 Livven 的回答(并点赞)。【参考方案2】:

加号 (+) 字符可以揭示这些方法之间的很多区别。在简单的 URI 中,加号表示“空格”。考虑向 Google 查询“快乐猫”:

https://www.google.com/?q=happy+cat

这是一个有效的 URI(试试看),EscapeUriString 不会修改它。

现在考虑向 Google 查询“happy c++”:

https://www.google.com/?q=happy+c++

这是一个有效的 URI(试试看),但它会搜索“happy c”,因为这两个加号被解释为空格。要修复它,我们可以将“happy c++”传递给EscapeDataString,然后瞧*

https://www.google.com/?q=happy+c%2B%2B

*)编码后的数据串实际上是“happy%20c%2B%2B”; %20 是十六进制的空格字符,%2B 是十六进制的加号。

如果您按照应有的方式使用UriBuilder,那么您只需要EscapeDataString 即可正确转义整个URI 的某些组件。 @Livven 对这个问题的回答进一步证明了确实没有理由使用EscapeUriString

【讨论】:

谢谢。如果您有一个需要编码的绝对 URI 字符串,例如"https://www.google.com/?q=happy c++",该怎么办。看起来我需要手动拆分“?”,还是有更好的方法? 如果您将整个 URL 作为参数传递给另一个 URL,请使用 EscapeDataString。如果您提供的 URL 是实际 URL,那么是的,您只想拆分 ?【参考方案3】:

我没有找到令人满意的现有答案,因此我决定深入挖掘以解决此问题。令人惊讶的是,答案很简单:

(几乎)没有正当理由使用Uri.EscapeUriString。如果您需要对字符串进行百分比编码,请始终使用Uri.EscapeDataString*

* 请参阅最后一段以了解有效的用例。

这是为什么?根据documentation:

使用 EscapeUriString 方法准备一个未转义的 URI 字符串作为 Uri 构造函数的参数。

这真的没有意义。根据RFC 2396:

URI 始终采用“转义”形式,因为转义或取消转义已完成的 URI 可能会改变其语义。

虽然引用的 RFC 已被 RFC 3986 废弃,但这一点仍然存在。让我们通过一些具体的例子来验证它:

    你有一个简单的 URI,像这样:

     http://example.org/
    

Uri.EscapeUriString 不会改变它。

    您决定手动编辑查询字符串而不考虑转义:

     http://example.org/?key=two words
    

Uri.EscapeUriString 会(正确地)为你逃离空间:

    http://example.org/?key=two%20words

    您决定进一步手动编辑查询字符串:

     http://example.org/?parameter=father&son
    

但是,Uri.EscapeUriString 不会更改此字符串,因为它假定与符号表示另一个键值对的开始。这可能是也可能不是您想要的。

    您决定实际上希望key 参数为father&son,因此您通过转义与符号来手动修复先前的URL:

     http://example.org/?parameter=father%26son
    

不过,Uri.EscapeUriString 也会转义百分号字符,导致双重编码:

    http://example.org/?parameter=father%2526son

如您所见,将Uri.EscapeUriString 用于其预期目的使得无法将& 用作查询字符串中键或值的一部分,而不是用作多个键值对之间的分隔符。

这是因为,为了使它适合转义完整的 URI,它会忽略保留字符,只转义既不是保留也不是非保留的字符,顺便说一句,这与 documentation 相反。这样您就不会遇到 http%3A%2F%2Fexample.org%2F 这样的问题,但您确实会遇到上述问题。


最后,如果你的 URI 是有效的,它不需要被转义作为参数传递给 Uri 构造函数,如果它无效,那么调用Uri.EscapeUriString 也不是一个神奇的解决方案。实际上,它在很多(如果不是大多数)情况下都可以使用,但它绝不是可靠的。

您应该始终通过收集键值对和百分比编码来构建您的 URL 和查询字符串,然后将它们与必要的分隔符连接起来。您可以为此目的使用Uri.EscapeDataString,但不能使用Uri.EscapeUriString,因为如上所述,它不会转义保留字符。

仅当您不能这样做时,例如在处理用户提供的 URI 时,是否有必要使用 Uri.EscapeUriString 作为最后的手段。但前面提到的警告也适用——如果用户提供的 URI 不明确,则结果可能不理想。

【讨论】:

哇,感谢您终于澄清了这个问题。前两个答案不是很有帮助。 完全正确。 EscapeUriString(类似于 Win32 中 EscapeUrl 的默认行为)是由不懂 URI 或转义的人创建的。创建采用格式错误的 URI 并有时将其转换为预期版本的东西是一种错误的尝试。但它没有可靠地执行此操作所需的信息。它也经常被用来代替 EscapeDataString,这也是非常有问题的。我希望 EscapeUriString 不存在。每次使用都是错误的。 很好地解释了+1,这比接受链接的答案要好得多 这个答案需要更多的关注。这是正确的方法。其他答案的情况不会产生预期的结果。 ...当然encodeURI/Uri.EscapeUriString 不需要像encodeURIComponent/Uri.EscapeDataString 那样频繁(因为您什么时候需要在uri 上下文中使用盲网址) ,但这并不意味着它没有它的位置。【参考方案4】:

source 中的评论清楚地说明了差异。为什么不通过 XML 文档 cmets 提供此信息对我来说是个谜。

EscapeUriString:

此方法将转义任何非保留字符或 无保留字符,包括百分号。注意 EscapeUriString 也不会转义“#”符号。

EscapeDataString:

此方法将转义任何不是未保留的字符 字符,包括百分号。

所以区别在于它们处理保留字符的方式。 EscapeDataString 逃脱它们; EscapeUriString 没有。

根据RFC,保留字符为::/?#[]@!$&'()*+,;=

为了完整起见,未保留的字符是字母数字和-._~

这两种方法都转义了既不是保留也不是非保留的字符。

我不同意notion 的普遍看法,即EscapeUriString 是邪恶的。我认为只转义 illegal 字符(例如空格)而不转义 reserved 字符的方法很有用。但它在处理% 字符的方式上确实有一个怪癖。百分比编码字符(% 后跟 2 个十六进制数字)在 URI 中是合法。我认为如果EscapeUriString 检测到这种模式并避免在% 立即以2 个十六进制数字进行编码时,它会更有用。

【讨论】:

【参考方案5】:

一个简单的例子

var data = "example.com/abc?DEF=あいう\x20えお";

Console.WriteLine(Uri.EscapeUriString(data));
Console.WriteLine(Uri.EscapeDataString(data));
Console.WriteLine(System.Net.WebUtility.UrlEncode(data));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(data));

/*
=>
example.com/abc?DEF=%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86+%E3%81%88%E3%81%8A
example.com%2fabc%3fDEF%3d%e3%81%82%e3%81%84%e3%81%86+%e3%81%88%e3%81%8a
*/

【讨论】:

【参考方案6】:

我使用加密字符串作为 URL 参数(例如http://example.com/Test/myencryptedkey/param2/param3),因此没有任何 C# 加密方法可以提供安全的 url 参数。我最终使用了以下模式:

加密期间: Uri.EscapeDataString(myencryptedkey).Replace('%', '~');

在解密期间: Uri.UnescapeDataString(myencryptedkey.Replace('~', '%'));

请注意,在加密期间替换发生在 EscapeDataString() 之后,而在解密期间替换发生在 UnescapeDataString() 之前;

【讨论】:

以上是关于uri和url有啥关系和区别?的主要内容,如果未能解决你的问题,请参考以下文章

URI、URL 和 URN 有啥区别? [复制]

请问URI和URL有啥区别?

Java中的资源、URI、URL、路径和文件有啥区别?

URI和URL的区别和联系

URI和URL的区别

URL与IP地址有啥关系与区别