•JDK1.4版本开始,JDK提供了新的IO操作API, NIO提供多路(non-blocking) 非阻塞式的高伸缩性网络I/O,从而提高了效率,NIO主要有三大核心组件:Channel、Buffer和Selector,这里重点学习前两个, Selector 将在网络编程章节详细介绍。
•Buffer是一个抽象类,Buffer类型变量对应的对象代表一块缓冲区,ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer和ShortBuffer类都是Buffer抽象类的子类,其中ByteBuffer最常用。
•ByteBuffer常用方法:
1.static ByteBuffer allocate(int capacity):分配一个新的字节缓冲区。√
2.int capacity() :返回此缓冲区的容量。
3.ByteBuffer put(byte b):将字节类型数据写入当前位置的缓冲区,然后当前位置+1,位置从0开始。
4.byte[] array() :将ByteBuffer类型的数据转为byte数组。√
5.int position():返回缓冲区当前位置。
6.Buffer flip() ):翻转缓冲区,将position置零。√
7.boolean hasRemaining():判断缓冲区是否含有数据 。
8.byte get()读取缓冲区当前位置的字节,然后当前位置+1。√
9.Buffer clear():清除缓冲区,位置归零。√
1-5:
public class Test {
public static void main(String[] args) {
ByteBuffer buffer=ByteBuffer.allocate(1024);
System.out.println(buffer.position());
}
}
结果:0
public class Test {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
byte a = 1;// 要定义下,不然默认是int类型
buffer.put(a);
System.out.println(buffer.position());
}
}
public class Test {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
byte a = 1;// 要定义下,不然默认是int类型
buffer.put(a);
buffer.flip();
System.out.println(buffer.position());
}
}
结果是0
boolean hasRemaining():告诉当前位置和极限之间是不是存在元素,有的话返回true。
public class Test {
public static void main(String[] args) {
ByteBuffer buffer=ByteBuffer.allocate(2);
System.out.println(buffer.get());
System.out.println(buffer.hasRemaining());
System.out.println(buffer.get());
System.out.println(buffer.hasRemaining());
}
}
结果:
0
true
0
false
默认极限跟大小一样,所以,到最后一个的时候到极限了,false。
public class Test {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
byte a = 1, b = 3;// 要定义下,不然默认是int类型
buffer.put(a);//存入一个数据,当前位置0加1变为1
buffer.put(b);//存入第二个,位置变为2
buffer.flip();//一下清零
System.out.println(buffer.get());//得到第一个数据,位置加1
System.out.println(buffer.position());
}
}
结果:
1
1
public class Test {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
byte a = 1;
buffer.put(a);
System.out.println(buffer.get());//a此时在0的位置上,但当前位置是1,得到的当然是0
System.out.println(buffer.position());//上一步get过后位置又加1
}
}
结果:
0
2
public class Test {
public static void main(String[] args) {
try {
FileInputStream fileInputStream=new FileInputStream("D:\\1.txt");
FileChannel fileChannel= fileInputStream.getChannel();
ByteBuffer buffer=ByteBuffer.allocate(1024);
while(fileChannel.read(buffer)!=-1) {
System.out.println(buffer.position());
buffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果:8
•Channel是一个接口,该接口类型变量指向的对象代表一个数据传输通道,Channel对象是面向缓冲区的:数据总是从通道读取到缓冲区(Buffer类型对象),或从缓冲区(Buffer类型对象)写入到通道中。
•Channel接口主要实现类如下:
1.FileChannel:从文件中读写数据。
2.DatagramChannel:通过UDP读写网络中的数据。
3.SocketChannel:通过TCP读写网络中的数据。
4.ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样,对每一个新进来的连接都会创建一个SocketChannel。
•只能通过调用FileInputStream和FileOutputStream类中getChannel方法获取FileChannel对象,FileChannel类常用方法如下:
1.int read(ByteBuffer dst):从通道的当前文件位置开始将数据读取到缓冲区,然后以实际读取的字节数更新文件位置;返回实际读取的字节数,如果已达到通道末尾, 则返回-1 。
2.void close():关闭通道。
public class Test {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
for (int i = 0; i < 1024; i++) {
System.out.println(buffer.get() + "," + i + "," + buffer.hasRemaining());
}
}
}