【java】源码详解java NIO(1)_初识NIO

【java】源码详解java NIO(一)_初识NIO

末日前,复习复习J2SE,java nio,先回顾一些基础常识


I/O 简介

I/O ? 或者输入/输出 ? 指的是计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。单独的程序一般是让系统为它们完成大部分的工作。
在 Java 编程中,直到最近一直使用 流 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接触。它也在内部使用,用于将对象转换为字节,然后再转换回对象。
NIO 与原来的 I/O 有同样的作用和目的,但是它使用不同的方式? 块 I/O。正如您将在本教程中学到的,块 I/O 的效率可以比流 I/O 高许多。


什么是NIO

新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的。NIO 弥补了原来的 I/O 的不足,它在标准 Java 代码中提供了高速的、面向块的 I/O。通过定义包含数据的类,以及通过以块的形式处理这些数据,NIO 不用使用本机代码就可以利用低级优化,这是原来的 I/O 包所无法做到的。
在本教程中,我们将讨论 NIO 库的几乎所有方面,从高级的概念性内容到底层的编程细节。除了学习诸如缓冲区和通道这样的关键 I/O 元素外,您还有机会看到在更新后的库中标准 I/O 是如何工作的。您还会了解只能通过 NIO 来完成的工作,如异步 I/O 和直接缓冲区。
在本教程中,我们将使用展示 NIO 库的不同方面的代码示例。几乎每一个代码示例都是一个大的 Java 程序的一部分,您可以在 参考资料 中找到这个 Java 程序。在做这些练习时,我们推荐您在自己的系统上下载、编译和运行这些程序。在您学习了本教程以后,这些代码将为您的 NIO 编程努力提供一个起点。
本教程是为希望学习更多关于 JDK 1.4 NIO 库的知识的所有程序员而写的。为了最大程度地从这里的讨论中获益,您应该理解基本的 Java 编程概念,如类、继承和使用包。多少熟悉一些原来的 I/O 库(来自 java.io.* 包)也会有所帮助。
虽然本教程要求掌握 Java 语言的工作词汇和概念,但是不需要有很多实际编程经验。除了彻底介绍与本教程有关的所有概念外,我还保持代码示例尽可能短小和简单。目的是让即使没有多少 Java 编程经验的读者也能容易地开始学习 NIO。


为什么要使用 NIO

NIO 的创建目的是为了让 Java 程序员可以实现高速 I/O 而无需编写自定义的本机代码。NIO 将最耗时的 I/O 操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。


建议详细研读 深入分析 Java I/O 的工作机制一文,这些入门常识必须掌握透彻,要么,就很难让人相信自己是程序员。


好,看示例程序源代码:

package dec;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

/**
 * 
 * 
 * <p>
 * Title: nio测试(一)页面读取
 * </p>
 * 
 * <p>
 * Description: 示例 业务类
 * </p>
 * 
 * <p>
 * Copyright: Copyright (c) 2012
 * </p>
 * 
 * 
 * @author dml@2012-12-21
 * @version 1.0
 */
public class NioReadPage {

	private Charset charset = Charset.forName("GBK");// 创建GBK字符集
	private SocketChannel channel;

	public void readHTMLContent() {
		try {
			InetSocketAddress socketAddress = new InetSocketAddress(
					"www.baidu.com", 80);
			// step1:打开连接
			channel = SocketChannel.open(socketAddress);
			// step2:发送请求,使用GBK编码
			channel.write(charset.encode("GET " + "/ HTTP/1.1" + "\r\n\r\n"));
			// step3:读取数据
			ByteBuffer buffer = ByteBuffer.allocate(1024);// 创建1024字节的缓冲
			while (channel.read(buffer) != -1) {
				buffer.flip();// flip方法在读缓冲区字节操作之前调用。作用:将缓存字节数组的指针设置为数组的开始序列即数组下标0
				System.out.println(charset.decode(buffer));
				System.out.println("--------------------");
				// 使用Charset.decode方法将字节转换为字符串
				buffer.clear();// 清空缓冲
			}
		} catch (IOException e) {
			System.err.println(e.toString());
		} finally {
			if (channel != null) {
				try {
					channel.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public static void main(String[] args) {
		new NioReadPage().readHTMLContent();
	}
}


执行结果:

HTTP/1.1 200 OK
Date: Fri, 21 Dec 2012 01:28:24 GMT
Server: BWS/1.0
Content-Length: 10202
Content-Type: text/html;charset=gbk
Cache-Control: private
Expires: Fri, 21 Dec 2012 01:28:24 GMT
Set-Cookie: BAIDUID=8460D9B3EDEFA79987FB13AD153AE413:FG=1; expires=Fri, 21-Dec-42 01:28:24 GMT; path=/; domain=.baidu.com
P3P: CP=" OTI DSP COR IVA OUR IND COM "
Connection: Keep-Alive


--------------------
<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html;charset=gb2312"><title>百度一下,你就知道      </title><style>html,body{height:100%;}html{overflow-y:auto}#wrapper{position:relative;_position:;min-height:100%}#content{padding-bottom:100px;text-align:center;}#ftCon{height:100px;position:absolute;bottom:44px;text-align:center;width:100%;margin:0 auto;z-index:0;overflow:hidden;}#ftConw{width:720px;margin:0 auto;}body{font:12px arial;text-align:;background:#fff}body,p,form,ul,li{margin:0;padding:0;list-style:none}body,form,#fm{position:relative}td{text-align:left}img{border:0}a{color:#00c}a:active{color:#f60}#u{color:#999;padding:4px 10px 5px 0;text-align:right}#u a{margin:0 5px}#u .reg{margin:0}#m{width:720px;margin:0 auto;}#nv a,#nv b,.btn,#lk{font-size:14px}#fm{padding-left:110px;text-align:left;z-index:1;}input{border:0;padding:0}#nv{height:19px;font-size:16px;margin:0 0 4px;text-align:left;text-indent:137px;}.s_ipt_wr{width:418px;height:30px;display:inline-block;margin-right:5px;
--------------------
background:url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png) no-repeat -304px 0;border:1px solid #b6b6b6;border-color:#9a9a9a #cdcdcd #cdcdcd #9a9a9a;vertical-align:top}.s_ipt{width:405px;height:22px;font:16px/22px arial;margin:5px 0 0 7px;background:#fff;outline:none;-webkit-appearance:none}.s_btn{width:95px;height:32px;padding-top:2px\9;font-size:14px;background:#ddd url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png);cursor:pointer}.s_btn_h{background-position:-100px 0}.s_btn_wr{width:97px;height:34px;display:inline-block;background:url(http://s1.bdstatic.com/r/www/img/i-1.0.0.png) no-repeat -202px 0;*position:relative;z-index:0;vertical-align:top}#lg img{vertical-align:top;margin-bottom:3px}#lk{margin:33px 0}#lk span{font:14px "宋体"}#lm{height:60px}#lh{margin:16px 0 5px;word-spacing:3px}.tools{position:absolute;top:-4px;*top:10px;right:7px;}#mHolder{width:62px;position:relative;z-index:296;display:none}#mCon{height:18px;line-height:18px;position:absolute;cursor:pointer;padding:0 18px 0 0;background:url(htt
--------------------
p://s1.bdstatic.com/r/www/img/bg-1.0.0.gif) no-repeat right -134px;background-position:right -136px\9}#mCon span{color:#00c;cursor:default;display:block}#mCon .hw{text-decoration:underline;cursor:pointer}#mMenu a{width:100%;height:100%;display:block;line-height:22px;text-indent:6px;text-decoration:none;filter:none\9}#mMenu,#user ul{box-shadow:1px 1px 2px #ccc;-moz-box-shadow:1px 1px 2px #ccc;-webkit-box-shadow:1px 1px 2px #ccc;filter: progid:DXImageTransform.Microsoft.Shadow(Strength=2, Direction=135, Color="#cccccc")\9;}#mMenu{width:56px;border:1px solid #9b9b9b;list-style:none;position:absolute;right:27px;top:28px;display:none;background:#fff}#mMenu a:hover{background:#ebebeb}#mMenu .ln{height:1px;background:#ebebeb;overflow:hidden;font-size:1px;line-height:1px;margin-top:-1px}#cp,#cp a{color:#666666;}#seth{display:none;behavior:url(#default#homepage)}#setf{display:none;}#sekj{margin-left:14px;}</style>
<script type="text/javascript">function h(obj){obj.style.behavior='url(#default#homepage)';var a = obj.s
--------------------
etHomePage('http://www.baidu.com/');}</script></head>

<body><div id="wrapper"><div id="content">

<div id="ie6tipcon"></div>


<div id="u"><a href="http://www.baidu.com/gaoji/preferences.html" name="tj_setting">搜索设置</a>|<a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login" id="lb" onclick="return false;">登录</a><a href="https://passport.baidu.com/v2/?reg®Type=1&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" target="_blank" name="tj_reg" class="reg">注册</a></div>
<div id="m"><p id="lg"><img src="http://www.baidu.com/img/baidu_sylogo1.gif" width="270" height="129" ></p>
<p id="nv"><a href="http://news.baidu.com">新 闻</a> <b>网 页</b> <a href="http://tieba.baidu.com">贴 吧</a> <a href="http://zhidao.baidu.com">知 道</a> <a href="http://music.baidu.com">音 乐</a> <a href="http://image.baidu.com">图 片</a> <a href="http://video.baidu.com">视 频</a> <a href="http://map.baidu.com">地 图</a></p><div id="fm"><form na
--------------------
me="f" action="/s"><span class="s_ipt_wr"><input type="text" name="wd" id="kw" maxlength="100" class="s_ipt"></span><input type="hidden" name="rsv_bp" value="0"><input type="hidden" name="rsv_spt" value="3"><span class="s_btn_wr"><input type="submit" value="百度一下" id="su" class="s_btn" onmousedown="this.className='s_btn s_btn_h'" onmouseout="this.className='s_btn'"></span></form><span class="tools"><span id="mHolder"><div id="mCon"><span>输入法</span></div></span></span><ul id="mMenu"><li><a href="#" name="ime_hw">手写</a></li><li><a href="#" name="ime_py">拼音</a></li><li class="ln"></li><li><a href="#" name="ime_cl">关闭</a></li></ul></div>
<p id="lk"><a href="http://baike.baidu.com">百科</a> <a href="http://wenku.baidu.com">文库</a> <a href="http://www.hao123.com">hao123</a><span> | <a href="http://www.baidu.com/more/">更多>></a></span></p><p id="lm"><a href="http://map.baidu.com/maps/shuangdan/?from=sy" title="" target="_blank" style="font-family: 宋体,Arial,Helvetica,sans-serif;">这一天,在一
--------------------
起!上百度地图,约会有“礼”!</a></p>
</div></div><div id="ftCon"><div id="ftConw"><p ><a id="seth" onClick="h(this)" href="/" onmousedown="return ns_c({'fm':'behs','tab':'homepage','pos':0})">把百度设为主页</a><a id="setf" href="http://www.baidu.com/cache/sethelp/index.html" onmousedown="return ns_c({'fm':'behs','tab':'favorites','pos':0})" target="_blank">把百度设为主页</a><span id="sekj"><a href="http://www.baidu.com/search/baidukuaijie_mp.html" target="_blank" onmousedown="return ns_c({'fm':'behs','tab':'kuaijie','pos':1})">把百度添加到桌面</a></span></p><p id="lh"><a href="http://e.baidu.com/?refer=888" onmousedown="return ns_c({'fm':'behs','tab':'btlink','pos':2})">加入百度推广</a> | <a href="http://top.baidu.com">搜索风云榜</a> | <a href="http://home.baidu.com">关于百度</a> | <a href="http://ir.baidu.com">About Baidu</a></p><p id="cp">©2012 Baidu <a href="/duty/">使用百度前必读</a> <a href="http://www.miibeian.gov.cn" target="_blank">京ICP证030173号</a> <img src="http://www.baidu.com/cache/globa
--------------------
l/img/gs.gif"></p></div></div>
</div></body>

<script>var bds={se:{},comm : {ishome : 1,sid : "",user : "",username : "",sugHost : "http://suggestion.baidu.com/su",loginAction : []}}</script><script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/global/js/home-2.2.js"></script><script>var bdUser = null;var w=window,d=document,n=navigator,k=d.f.wd,a=d.getElementById("nv").getElementsByTagName("a"),isIE=n.userAgent.indexOf("MSIE")!=-1&&!window.opera;(function(){if(/q=([^&]+)/.test(location.search)){k.value=decodeURIComponent(RegExp["\x241"])}})();if(n.cookieEnabled&&!/sug?=0/.test(d.cookie)){bds.se.sug();};function addEV(o, e, f){if(w.attachEvent){o.attachEvent("on" + e, f);}else if(w.addEventListener){ o.addEventListener(e, f, false);}}function G(id){return d.getElementById(id);}function ns_c(q){var p = encodeURIComponent(window.document.location.href), sQ = '', sV = '', mu='', img = window["BD_PS_C" + (new Date()).getTime()] = new Image();for (v in q) {sV = q[v];sQ += v + "=" + sV + "&";} m
--------------------
u= "&mu=" + p ;img.src = "http://nsclick.baidu.com/v.gif?pid=201&pj=www&rsv_sid=&" + sQ + "path="+p+"&t="+new Date().getTime();return true;}if(/\bbdime=[12]/.test(d.cookie)){document.write('<script src=http://s1.bdstatic.com/r/www/cache/ime/js/openime-1.0.1.js><\/script>');}(function(){var u = G("u").getElementsByTagName("a"), nv = G("nv").getElementsByTagName("a"), lk = G("lk").getElementsByTagName("a"), un = "";var tj_nv = ["news","tieba","zhidao","mp3","img","video","map"];var tj_lk = ["baike","wenku","hao123","more"];un = bds.comm.user == "" ? "" : bds.comm.user;function _addTJ(obj){addEV(obj, "mousedown", function(e){var e = e || window.event;var target = e.target || e.srcElement;ns_c({'fm':'behs','tab':target.name||'tj_user','un':encodeURIComponent(un)});});}for(var i = 0; i < u.length; i++){_addTJ(u[i]);}for(var i = 0; i < nv.length; i++){nv[i].name = 'tj_' + tj_nv[i];}for(var i = 0; i < lk.length; i++){lk[i].name = 'tj_' + tj_lk[i];}})();(function() {var links = {'tj_news':   ['word', 'http://news.bai
--------------------
du.com/ns?tn=news&cl=2&rn=20&ct=1&ie=utf-8'],'tj_tieba':  ['kw', 'http://tieba.baidu.com/f?ie=utf-8'],'tj_zhidao': ['word', 'http://zhidao.baidu.com/search?pn=0&rn=10&lm=0'],'tj_mp3':    ['key', 'http://music.baidu.com/search?fr=ps&ie=utf-8'],'tj_img':    ['word', 'http://image.baidu.com/i?ct=201326592&cl=2&nc=1&lm=-1&st=-1&tn=baiduimage&istype=2&fm=&pv=&z=0&ie=utf-8'],'tj_video':  ['word', 'http://video.baidu.com/v?ct=301989888&s=25&ie=utf-8'],'tj_map':    ['wd', 'http://map.baidu.com/?newmap=1&ie=utf-8&s=s'],'tj_baike':  ['word', 'http://baike.baidu.com/search/word?pic=1&sug=1&enc=utf8'],'tj_wenku':  ['word', 'http://wenku.baidu.com/search?ie=utf-8']};var domArr = [G('nv'), G('lk')],kw = G('kw');for (var i = 0, l = domArr.length; i < l;  i++) {domArr[i].onmousedown = function(e) {e = e || window.event;var target = e.target || e.srcElement,name = target.getAttribute('name'),items = links[name],reg = new RegExp('^\\s+|\\s+\x24'),key = kw.value.replace(reg, '');if (items) {if (key.length > 0) {var wd = items[0
--------------------
], url = items[1],url = url + ( name === 'tj_map' ? encodeURIComponent('&' + wd + '=' + key)  : ( ( url.indexOf('?') > 0 ? '&' : '?' ) + wd + '=' + encodeURIComponent(key)  ) );target.href = url;} else {target.href = target.href.match(new RegExp('^http://.+\\.baidu\\.com'))[0];}}name && ns_c({'fm': 'behs','tab': name,'query': encodeURIComponent(key),'un': encodeURIComponent(bds.comm.user || '')    });};}})();addEV(w,"load",function(){k.focus()});w.onunload=function(){};</script><script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/global/js/tangram-1.3.4c1.0.js"></script><script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/user/js/u-1.3.4.js"></script><script>(function(){var C=G("lm").getElementsByTagName("A");for(var B=0,A=C.length;B<A;B++){var D=C[B];addEV(D,"mousedown",(function(E,F){return function(){ns_c({fm:"behs",tab:"bdlnk",p1:F+1,title:E.innerHTML,url:E.href})}})(D,B))}})();</script>



</html>



<!--12efc81ce1905ff0-->
--------------------

之前很多同学有询问,程序员写程序,不怎么用到网络知识,为什么有些公司笔试的时候要考网络?

当你遇见上面这些信息时,发现很容易就懂了这些表述的是什么意思,默默感谢感谢学校的网络原理老师吧。


p.s.本来想一篇总结完NIO,发现东西确实不少,分治之。如果看完上述文字后记住了nio 是 java New IO 的简称,是 jdk1.4 里提供的新 api ,就达到了最基本的目的,接下来,会陆续源码详解NIO的一些特性。

dml@wip 2012.12.21