本文章来自于本人个人博客:java nio 通道(一)
通道用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效的传输数据。
在学习channel以前,先来观察一下channel的家族吧:
一,打开通道
通道分为File I/O和Stream I/O,对应的类分别为FileChannel和 SocketChannel,ServerSocketChannel, DatagramChannel。通道可以用多种方式创建,但是一个FileChannel对象却只能通过在一个打开的RandomAccessFile,FileInputStream和FileOutputStream对象上调用getChannel()方法来获取。
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("localhost",port));
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress("localhost",port));
DatagramChannel dc = Datagram.open();
RandomAccessFile raf = new RandomAccessFile("filepath","r");
FileChannel fc = raf.getChannel();
在使用IO流创建文件通道时,如果RandomAccessFile创建的时候是只读,则通道也是只读,如果设置的是写或者读写模式,则可修改数据。因此,通过FileChannel得到的ByteBuffer也将随着只读而只读,读写而读写。
二,矢量I/O
矢量I/O即Scatter/Gather,scatter的功能是将一个大缓冲区的数据一次性读入几个小的缓冲区中,而gather的功能是将几个小缓冲区的数据一次性读入一个大的缓冲区中,然后沿着通道发送出去。Scatter/Gather应该使用直接的ByteBuffer以从本地I/O获取最大性能优势。
ByteBuffer header = ByteBuffer.allocateDirect(10);
ByteBuffer body = ByteBuffer.allocateDirect(80);
ByteBuffer[] buffers = {header, body};
int bytesRead = channel.read(buffers);
here is a simple example:
通道用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效的传输数据。

在学习channel以前,先来观察一下channel的家族吧:
一,打开通道
通道分为File I/O和Stream I/O,对应的类分别为FileChannel和 SocketChannel,ServerSocketChannel, DatagramChannel。通道可以用多种方式创建,但是一个FileChannel对象却只能通过在一个打开的RandomAccessFile,FileInputStream和FileOutputStream对象上调用getChannel()方法来获取。
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("localhost",port));
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress("localhost",port));
DatagramChannel dc = Datagram.open();
RandomAccessFile raf = new RandomAccessFile("filepath","r");
FileChannel fc = raf.getChannel();
在使用IO流创建文件通道时,如果RandomAccessFile创建的时候是只读,则通道也是只读,如果设置的是写或者读写模式,则可修改数据。因此,通过FileChannel得到的ByteBuffer也将随着只读而只读,读写而读写。
二,矢量I/O
矢量I/O即Scatter/Gather,scatter的功能是将一个大缓冲区的数据一次性读入几个小的缓冲区中,而gather的功能是将几个小缓冲区的数据一次性读入一个大的缓冲区中,然后沿着通道发送出去。Scatter/Gather应该使用直接的ByteBuffer以从本地I/O获取最大性能优势。
ByteBuffer header = ByteBuffer.allocateDirect(10);
ByteBuffer body = ByteBuffer.allocateDirect(80);
ByteBuffer[] buffers = {header, body};
int bytesRead = channel.read(buffers);
here is a simple example:
package com;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
public class TestByteOrder {
/**
* 功能:
* 作者: jiangfuqiang
* 创建日期:2014-8-3
* 修改者: mender
* 修改日期: modifydate
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
File file = new File("/Users/jiang/Desktop/3.txt");
if(!file.exists()) {
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
GatheringByteChannel gbc = fos.getChannel();
ByteBuffer buffer1 = ByteBuffer.allocateDirect(10);
buffer1.put((byte)'j');
buffer1.put((byte)'i');
buffer1.put((byte)'a');
buffer1.put((byte)'n');
buffer1.put((byte)'g');
buffer1.put((byte)'j');
buffer1.put((byte)'i');
buffer1.put((byte)'a');
buffer1.put((byte)'n');
buffer1.put((byte)'\n');
ByteBuffer buffer2 = ByteBuffer.allocateDirect(20);
buffer2.put((byte)'j');
buffer2.put((byte)'i');
buffer2.put((byte)'a');
buffer2.put((byte)'n');
buffer2.put((byte)'g');
buffer2.put((byte)'f');
buffer2.put((byte)'u');
buffer2.put((byte)'h');
buffer2.put((byte)'x');
buffer2.put((byte)'n');
buffer2.put((byte)'j');
buffer2.put((byte)'i');
buffer2.put((byte)'a');
buffer2.put((byte)'n');
buffer2.put((byte)'g');
buffer2.put((byte)'f');
buffer2.put((byte)'u');
buffer2.put((byte)'h');
buffer2.put((byte)'x');
buffer2.put((byte)'\n');
ByteBuffer buffer3 = ByteBuffer.allocateDirect(30);
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
buffer3.put((byte)'j');
// buffer3.put((byte)'j');
// buffer3.put((byte)'j');
//一定要记得在写入以前调用flip方法
buffer1.flip();
buffer2.flip();
buffer3.flip();
ByteBuffer[] buffers = {buffer1,buffer2,buffer3};
while(gbc.write(buffers) > 0) {
}
gbc.close();
FileInputStream fis = new FileInputStream(file);
ScatteringByteChannel sbc = fis.getChannel();
ByteBuffer b1 = ByteBuffer.allocateDirect(10);
ByteBuffer b2 = ByteBuffer.allocateDirect(20);
ByteBuffer b3 = ByteBuffer.allocateDirect(30);
ByteBuffer[] bs = {b1,b2,b3};
sbc.read(bs);
for(ByteBuffer bb : bs) {
bb.flip();
//注意,这个数组的初始化一定要放在flip()方法的后面,不然会将所读取的数据截断
byte[] data = new byte[bb.remaining()];
while(bb.hasRemaining()) {
//System.out.println(bb.get());
bb.get(data);
if(data.length > 0) {
System.out.print(data.length + " data=" + new String(data));
}
data = new byte[bb.remaining()];
}
bb.clear();
}
}
}
下一篇我们将一起来学习文件通道
下一篇我们将一起来学习文件通道