讲到NIO 不妨从老的IO 说起。

老的I/O 核心接口有2个: 一个是 InputStream/OutputStream (字节流),一次处理一个字节,Reader/Writer (字符流) ,一次处理一个字符。

NIO 是从JDK 1.4 才有的,她最基本的数据类型是Channel 和Buffer.

Channel表示数据的源头或者目的地,用于向Buffer提供数据或者读取Buffer的数据。

Buffer是一个连续的内存块,是NIO数据读写的中转地.

NIO有7种基本的Buffer类型,每种类型对应一个基本类型。

 

Buffer的结构包含3个变量

position: 读操作时(当前读的位置) / 写操作时(写了多少)

limit:       读操作时候(最多能读多少,等同于已经写的量) /写操作时候(最多能写多少,等同于整个buffer的容量)

capacity: 读操作时候(buffer容量) / 写操作时候(buffer容量)

 

Buffer的常见方法:

flip(): 在读模式和写模式之间进行切换

clear():清空Buffer

 

 以下是一些小例子:

(1) NIO 从网络上读内容 ,我们这里演示从Baidu 上读取内容

 

  1. /** 
  2.  * @author charles.wang 
  3.  * @created Mar 9, 2011 10:31:35 AM 
  4.  * Description: 
  5.  */ 
  6. public class BaiduReader { 
  7.      
  8.     private Charset charset=Charset.forName("GBK");//创建GBK字符集 
  9.     private SocketChannel channel; 
  10.     public void readHTMLContext(){ 
  11.         try
  12.             System.out.println("Start reading the HTML context..."); 
  13.             InetSocketAddress socketAddress = new InetSocketAddress ("www.baidu.com",80); 
  14.             //Step 1: 打开连接,创建一个基于InetSocketAddress的SocketChannel 
  15.             //SocketChannel 是4种Channel中的一种 
  16.             channel = SocketChannel.open(socketAddress); 
  17.             //Step 2:发送请求,使用GBK编码 
  18.             channel.write(charset.encode("GET "+"/ HTTP/1.1"+"\r\n\r\n")); 
  19.             //Step 3:读取数据 
  20.             ByteBuffer buffer =ByteBuffer.allocate(1024); //创建1024字节的缓冲区 
  21.             //读取过程,直到读到文件的结尾 
  22.             while(channel.read(buffer) != -1 ){ 
  23.                 System.out.println(1); 
  24.                 buffer.flip();//buffer从写模式切换到读模式 
  25.                 //打印出字符编码之后的文字 
  26.                 System.out.println(charset.decode(buffer)); 
  27.                 buffer.clear();//清空缓冲区 
  28.             } 
  29.              
  30.              
  31.         }catch(IOException ex){ 
  32.             System.err.println(ex.toString()); 
  33.         }finally
  34.             if(channel != null){ 
  35.                 try
  36.                     channel.close(); 
  37.                 }catch(IOException e){ 
  38.                     e.printStackTrace(); 
  39.                 } 
  40.             } 
  41.         } 
  42.     } 
  43.     /** 
  44.      * @param args 
  45.      */ 
  46.     public static void main(String[] args) { 
  47.         // TODO Auto-generated method stub 
  48.         new BaiduReader().readHTMLContext(); 
  49.     } 
  50.      
  51.      
  52.  

 

(2)采用NIO来进行基于块的复制文件

 

  1. /** 
  2.  * @author charles.wang 
  3.  * @created Mar 9, 2011 10:00:37 AM 
  4.  * Description: 
  5.  */ 
  6. public class CopyFile { 
  7.  
  8.     /** 
  9.      * @param args 
  10.      */ 
  11.     public static void main(String[] args)throws Exception { 
  12.         // TODO Auto-generated method stub 
  13.         String infile="d:\\copyfrom.txt"
  14.         String outfile="d:\\copyto.txt"
  15.         //获取源文件和目标文件的输入输出流 
  16.         FileInputStream fin = new FileInputStream(infile); 
  17.         FileOutputStream fout = new FileOutputStream(outfile); 
  18.         //获取输入输出channel 
  19.         //可以通过一个输入输出流来获取一个相应的通道 
  20.         FileChannel fcin = fin.getChannel(); 
  21.         FileChannel fcout=fout.getChannel(); 
  22.         //创建缓冲区 
  23.         ByteBuffer buffer = ByteBuffer.allocate(1024); 
  24.         while(true){ 
  25.             //clear方法重设缓冲区,使得它可以接受读入的数据 
  26.             buffer.clear(); 
  27.             //从输入通道将数据读到缓冲区 
  28.             int  r = fcin.read(buffer); 
  29.             //read 方法返回读取的字节数,可能为0,如果它已经能够到达流的末尾,那么返回-1 
  30.             if(r==-1
  31.                 break
  32.             //flip方法可以让缓冲区将新读入的数据写入到另外一个通道 
  33.             buffer.flip(); 
  34.             //将数据写入到fcout的通道 
  35.             fcout.write(buffer); 
  36.         } 
  37.          
  38.     } 
  39.