Java之NIO

Posted HeYang

tags:

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

想要学习Java的Socket通信,首先要学习Java的IO和NIO基础,这方面可以阅读《Java NIO 系列教程》。  

下面展示自己代码熟悉Java的NIO编程的笔记。

 

1、缓冲区(Buffer)

/*
 * 一、缓冲区(Buffer):在Java 中负责数据的存取。缓冲区就是数组。用于存储不同数据类型的数据
 *       
 *       根据数据类型不同(boolean除外),提供了相应类型的缓冲区
 *         ByteBuffer 那么实际上最常用的,因为网络传输的字节就是Byte
 *      CharBuffer
 *       ShortBuffer
 *        IntBuffer
 *         LongBuffer
 *      FloatBuffer
 *      DoubleBuffer
 *     
 *    上述缓冲区的管理方式几乎一致,通过allocate()获取缓冲区
 *    
 *  二、缓冲区存储数据的两个核心方法
 *      put()  : 存入数据到缓冲区中
 *      get()  : 获取缓冲区中的数据
 *      
 *  三、缓冲区中的四个核心属性
 *      capacity : 容量,表示缓冲区中最大存储数据的容量
 *      limit    : 界限,标识缓冲区中可以操作数据的大小(limit后面的数据不能进行读写的)
 *      position : 位置,标识缓冲区中正在操作数据的位置
 *      
 *      mark     : 标记,标识记录当前position的位置,可以通过reset()恢复到mark的位置
 *  
 *      0 <= mark <= position <= limit <= capacity
 *  四、直接缓冲区和非直接缓冲区
 *      非直接缓冲区: 通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中。
 *      直接缓冲区 :  通过allockateDirect()方法分配直接缓存区,将缓冲区建立在物理内存中。可以提高效率。
 *                  如果有数据需要一直在内存空间中重复用,并且数据量不大的情况下,就用allockateDirect()这种方法。
 *                  毕竟内存空间是有限的。
 */

相关代码:

  1 package com.demo.test;
  2 
  3 import java.nio.ByteBuffer;
  4 
  5 public class TestBuffer {
  6     
  7     public void test3(){
  8         // 分配直接缓冲区
  9         ByteBuffer buf = ByteBuffer.allocate(1024);
 10         System.out.println(buf.isDirect());// 判断这个缓冲区是直接还是非直接的。
 11     }
 12     
 13     public void test2(){
 14         String str = "abcde";
 15         
 16         // 1、分配一个指定大小的缓冲区
 17         ByteBuffer buf = ByteBuffer.allocate(1024);
 18         
 19         // 2、利用put()存入数据到缓冲区中
 20         System.out.println("往buf插入所有字符串的bytes是:"+str.getBytes());
 21         buf.put(str.getBytes());
 22         
 23         buf.flip();// 将插入模式转为查询模式,就是查询position位置会回到0
 24         
 25         System.out.println("创建和缓冲区等长度的字节数组,用来从缓冲区取出字节并存储以待读取操作");
 26         byte[] dst  = new byte[buf.limit()];
 27         System.out.println("从缓冲区中去除0开始的2位字节数据放进数组dst中");
 28         buf.get(dst, 0, 2);
 29         System.out.println("打印dst字节数组"+new String(dst, 0, 2));
 30         System.out.println("现在缓冲区的操作起始位置:"+buf.position());
 31         
 32         // mark(); 标记
 33         System.out.println("标记");
 34         buf.mark();
 35         buf.get(dst, 2, 2);// 取出从2开始的2位字节数据放进
 36         System.out.println("打印dst字节数组"+new String(dst, 2, 2));
 37         System.out.println("现在缓冲区的操作起始位置:"+buf.position());
 38         
 39         // reset(); 回复到mark的位置
 40         buf.reset();
 41         System.out.println("reset重置之后,缓冲区的操作起始位置回到:"+buf.position());
 42         
 43         // 判断缓冲区中是否还有剩余的数据
 44         if(buf.hasRemaining()){
 45             // 获取缓冲区还可以操作的数量
 46             System.out.println("缓冲区还有可以操作的数量"+buf.remaining());
 47         }
 48     }
 49     
 50     public void test(){
 51         String str = "abcde";
 52         
 53         // 1、分配一个指定大小的缓冲区
 54         ByteBuffer buf = ByteBuffer.allocate(1024);
 55         System.out.println("--调用allocate之后--");
 56         System.out.println(buf.capacity());
 57         System.out.println(buf.limit());
 58         System.out.println("position:"+buf.position());
 59         
 60         // 2、利用put()存入数据到缓冲区中
 61         System.out.println("字符串的bytes是:"+str.getBytes());
 62         buf.put(str.getBytes());
 63 
 64         System.out.println("--调用put之后--");
 65         System.out.println(buf.capacity());
 66         System.out.println(buf.limit());
 67         System.out.println("position:"+buf.position());
 68         
 69         // 3、前面是存入数据的模式,存入5个字节之后,position的位置从原本0现在到5了
 70         buf.flip();
 71         //   现在要将存储数据模式改成读取模式,position的位置会变回为0
 72         
 73         System.out.println("--调用flip切换模式之后--");
 74         System.out.println(buf.capacity());
 75         System.out.println(buf.limit());
 76         System.out.println("position:"+buf.position());
 77         
 78         // 4、利用get()读取缓冲区中的数据
 79         byte[] dst = new byte[buf.limit()];// 创建和缓冲区一样大的字节数据
 80         buf.get(dst);
 81         System.out.println(new String(dst,0,dst.length));
 82         
 83         System.out.println("--调用get()切换模式之后--");
 84         System.out.println(buf.capacity());
 85         System.out.println(buf.limit());
 86         System.out.println("position:"+buf.position());// 打印输出的结果会发现position变回5了
 87         
 88         // 5、可重复读取
 89         buf.rewind();
 90         
 91         System.out.println("--调用rewind()切换模式之后--");
 92         System.out.println(buf.capacity());
 93         System.out.println(buf.limit());
 94         System.out.println("position:"+buf.position());
 95         
 96         // 6、清空缓冲区。但是缓冲区中的数据依然存在,但是出于“被遗忘”状态
 97         buf.clear();
 98         
 99         System.out.println("--调用clear()切换模式之后--");
100         System.out.println(buf.capacity());
101         System.out.println(buf.limit());
102         System.out.println("position:"+buf.position());
103         
104         // 看看缓冲区有没有数据
105         System.out.println((char)(buf.get()+1));
106         
107     }
108 }

 2、通道(Channel)

由java.nio.channels包定义的。Channel表示IO源与目标打开的连接。Channel类似于传统的“流”。只不过Channel本身不能直接访问数据,Channel只能与Buffer进行交互。

先完成文件的复制:

 
































以上是关于Java之NIO的主要内容,如果未能解决你的问题,请参考以下文章

Java.nio:最简洁的递归目录删除

java之socket编程(NIO)

Java NIO之通道

Java NIO之通道

Java NIO 之 Selector

Java之io nio aio 的区别