首页 > 代码库 > java nio 通道(一)

java nio 通道(一)

本文章来自于本人个人博客: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 = http://www.mamicode.com/new byte[bb.remaining()];>

下一篇我们将一起来学习文件通道


下一篇我们将一起来学习文件通道