URI和URL的区别
看开源框架经常看到会用到URL或者URI之类的,为什么要熟悉这个呢? 比如说你写一个网络程序,需要访问资源,资源位置信息最好封装起来,如果使用String表示,虽然可以使用,但是感觉挺low的。你用了URI或者URL,当你想获取这个资源位置信息的某个属性时怎么着也比String方便吧。
一、URI与URL的定义
URI :统一资源标志符(Uniform Resource Identifier)
URL:统一资源定位符(uniform resource location)
说白了,URI与URL都是定位资源位置的,就是表示这个资源的位置信息,就像经纬度一样可以表示你在世界的哪个角落。URI是一种宽泛的含义更广的定义,而URL则是URI的一个子集,就是说URL是URI的一部分。换句话说,每个URL都是URI,但是不是每个URI都是URL的。在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的,schema必须被指定。
URL与URI很像,两者的格式几乎差不多,但是我们接触的还是URL比较多,就以URL为例说明,URL提供了一种访问定位因特网上任意资源的手段,但是这些资源可以通过不同的方法(例如HTTP、FTP、SMTP)来访问,不管怎样,他都基本上由9个部分构成:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<fragment>
1 |
scheme |
获取资源使用的协议,例如http、ftp等,没有默认值 |
2 |
user:password |
用户名与密码,这个是一个特殊的存在,一般访问ftp时会用到,他显示的表明了访问资源的用户名与密码。但是这个可以不写,不写的话可能会让你输入用户名密码 |
3 |
host |
主机,访问那台主机,有时候可以是IP,有时候是主机名,例如www.baidu.com |
4 |
port |
端口,访问主机时的端口,如果http访问默认80,可以省略。 |
5 |
path |
通过host:port我们能找到主机,但是主机上文件很多,通过path则可以定位具体文件。例如www.baidu.com/file/index.html。则path是/file/index.html,表示我们访问/file/index.html这个文件,他很像linux上的路径 |
6 |
params |
这个很少见,主要作用就是像服务器提供额外的参数,用来表示本次请求的一些特性。例如ftp传输模式有两种,二进制和文本,你肯定不希望使用文本形式传输二进制图片,这样你的图片下载下来后可能没法看了。为了向应用程序提供更丰富的信息,URL中有个专门的部分来表示这种参数。例如ftp://file.qiandu.com/pub/guid.pdf;type=d其中的type=d就是params |
7 |
query |
通过get方式请求的参数,例如:www.qiandu.com/index.html?username=dgh&passwd=123 |
8 |
fragment |
例如www.qiandu.com/index.html#1。当html页面比较长时,我们通常会将其分为好几段,#1就可以 快速定位到某一段。 |
下面两个方法用于打印URL和URI的信息:
//打印RUL信息
public static void showURL(URL url){
System.out.println("---URL---------------------------------------------");
System.out.println("URL.toString : " + url.toString());
System.out.println("authority : " + url.getAuthority());
System.out.println("file : " + url.getFile());
System.out.println("protocol : " + url.getProtocol());
System.out.println("userInfo : " + url.getUserInfo());
System.out.println("host : " + url.getHost());
System.out.println("port : " + url.getPort());
System.out.println("path : " + url.getPath());
System.out.println("query : " + url.getQuery());
System.out.println("ref : " + url.getRef());
}
//打印RUI信息
public static void showURI( URI uri){
System.out.println("---URI---------------------------------------------");
System.out.println("URI.toString : " + uri.toString());
System.out.println("authority : " + uri.getAuthority());
System.out.println("SchemeSpecificPart : " + uri.getSchemeSpecificPart());
System.out.println("scheme : " + uri.getScheme());
System.out.println("userInfo : " + uri.getUserInfo());
System.out.println("host : " + uri.getHost());
System.out.println("port : " + uri.getPort());
System.out.println("path : " + uri.getPath());
System.out.println("query : " + uri.getQuery());
System.out.println("fragment : " + uri.getFragment());
System.out.println("________raw___________");
System.out.println("rawSchemeSpecificPart : " + uri.getRawSchemeSpecificPart());
System.out.println("rawUserInfo : " + uri.getRawUserInfo());
System.out.println("rawAuthority : " + uri.getRawAuthority());
System.out.println("rawPath : " + uri.getRawPath());
System.out.println("rawQuery : " + uri.getRawQuery());
System.out.println("rawFragment : " + uri.getRawFragment());
}
例子:
public static void main(String args[]) throws Exception {
String str = "http://www.baidu.com:8080/goods/index.html?ZH=China&ADDR=BeiJing#fragment";
showURL( new URL(str));
showURI( new URI(str));
}
结果:
打印结果和我们预想的是一样的,虽然有些字段的叫法不一样(如:协议,URL中叫procotol,RUI中叫scheme)。
二、URI和URL的编解码
需要注意的是,URI 会自动编解码其中的字符串,如果需要获取原生值,需要使用 `getRawXXX()` 方法,URL 不会自动编解码,且 URLEncoder / URLDecoder 类提供的编解码只适用于 HTML。
例子:
public static void main(String args[]) throws Exception {
String str = "http://www."+ URLEncoder.encode("百度","UTF-8")+".com:8080/goods/index.html?ZH="+URLEncoder.encode("中国","UTF-8")+"&ADDR="+URLEncoder.encode("北京","UTF-8")+"#"+URLEncoder.encode("片段","UTF-8");
showURL( new URL(str));
showURI( new URI(str));
}
结果:
三、URL读取资源
URL是绝对定位,于是就可以找到对应资源。 URL可以通过OpenConnection()获得一个URLConnection对象,而URLConnection可以通过connection()等方法对网络资源进行操作。所以,如果按照官方给出的提示,我们按照以下的方式读取一个网络资源:
public static void main(String[] args) throws Exception {
URL url = new URL("http://www.baidu.com");
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String temp=null;
while ((temp=reader.readLine())!=null) {
stringBuilder.append(temp);
}
System.out.println(stringBuilder.toString());
}
结果:
四、 URL的相对位置
在多文件位置描术时,其实只要知道一个基础路径,文件路径都相对这个基础路径。
现在已知文件夹a的路径为C:\Users\Administrator\Desktop\test\a,以a文件为基础路径,则a1.txt的相对路径为a1.txt,b1.txt的相对路径为../b/b1/.txt。
public static void main(String args[]) throws Exception {
URI baseURI = new URI("file:/C:/Users/Administrator/Desktop/test/a/");
URI a1URI = new URI("a1.txt");
URI b1URI = new URI("../b/b1.txt");
URI a1AbsoluteURI= baseURI.resolve(a1URI);
URI b1AbsoluteURI= baseURI.resolve(b1URI);
System.out.println(a1AbsoluteURI.toString());
System.out.println(b1AbsoluteURI.toString());
System.out.println(getContent(a1AbsoluteURI.toURL()));
System.out.println(getContent(b1AbsoluteURI.toURL()));
}
//获取文件内容
public static String getContent(URL url)throws Exception {
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String temp=null;
while ((temp=reader.readLine())!=null) {
stringBuilder.append(temp);
}
return stringBuilder.toString();
}
结果:
上一篇: 芭蕉的营养成分,你都完全了解了吗
推荐阅读
-
Intel(英特尔) 酷睿i5 2代系列和3代系列的区别是什么?
-
CPU盒装和散装的区别 盒装与散装如何选择
-
CPU三级缓存的作用 二级缓存和三级缓存有什么区别
-
因特尔奔腾B960和2020M处理器之间的各种区别介绍
-
i7-7740X和i7-7700K的区别是什么 i7-7740X与i7-7700K性能对比测试图解
-
R3 1200和i3 7100哪个好?R3-1200与i3-7100的区别对比详细评测
-
SQL联合查询inner join、outer join和cross join的区别详解
-
js中apply和Math.max()函数的问题及区别介绍
-
jQuery中attr()和prop()在修改checked属性时的区别
-
VO和DO的区别