首页 > 代码库 > Java之NIO
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