nio学习记录 : start(buffer channel selector)

Buffer的capacity,limit,position

limit,position的含义取决于是读模式还是写模式

 

capacity

buffer的大小

 

limit

write:和capacity一样,表示能写多少

read:表示最多可读多少

 

position

write:write index,最大值 capacity-1

read:read index,从写模式切换到读模式时,position会被重置为0

 

 

buffer的类型

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer
public class FileTest {

    public static void main(String[] args) throws IOException {

        RandomAccessFile raFile = new RandomAccessFile("/Users/shifulong/monitor_contact.sql", "rw");
        FileChannel fileChannel = raFile.getChannel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(64);
        
        while (fileChannel.read(byteBuffer) != -1) {//read in to buffer

            byteBuffer.flip();

            while (byteBuffer.hasRemaining()) {
                System.out.print((char) byteBuffer.get());
            }

            byteBuffer.clear();
        }
    }
}

 

 

典型的几个方法

ByteBuffer byteBuffer = ByteBuffer.allocate(64);//获取一个64大小的buffer

byteBuffer.flip();//将buffer从写模式切换到读模式

byteBuffer.rewind();//将position设为0,可重读数据

byteBuffer.clear();//清除buffer position设为0,如果buffer中还有数据没有读,就丢失了
byteBuffer.compact();//清除buffer,并把没读的数据copy到起始处,position设到最后一个没读的数据后面,可以追加写

byteBuffer.mark();//标记一个特定postion
byteBuffer.reset();//恢复标记,恢复到标记的position

 

 分散&聚集

多个buffer写到channel中

从channel总读到多个buffer中

//分散
public void scatter() throws IOException {

    RandomAccessFile randomAccessFile = new RandomAccessFile("", "");
    FileChannel fileChannel = randomAccessFile.getChannel();

    ByteBuffer head = ByteBuffer.allocate(16);
    ByteBuffer body = ByteBuffer.allocate(64);

    fileChannel.read(new ByteBuffer[]{head, body});//读到多个buffer中,不方便操作不定长的消息
}

//聚集
public void gather() throws IOException {

    RandomAccessFile randomAccessFile = new RandomAccessFile("", "");
    FileChannel fileChannel = randomAccessFile.getChannel();

    ByteBuffer buffer1 = ByteBuffer.allocate(16);//need put byte to buffer
    ByteBuffer buffer2 = ByteBuffer.allocate(64);

    fileChannel.write(new ByteBuffer[]{buffer1, buffer2});//多个buffer写到channel,可以操作不定长的消息
}

 

通道之间的数据传输

只要两个通道之间有一个是FileChannel,就可以将一个channel传输到另一个channel

    public static void from() throws IOException {
        RandomAccessFile fromFile = new RandomAccessFile("/Users/shifulong/monitor_contact.sql", "rw");
        FileChannel fromChannel = fromFile.getChannel();

        RandomAccessFile toFile = new RandomAccessFile("/Users/shifulong/monitor_contact_to.sql", "rw");
        FileChannel toChannel = toFile.getChannel();

        long position = 0;

        toChannel.transferFrom(fromChannel,position,fromChannel.size());
        toChannel.close();
        fromChannel.close();
    }

    public static void to() throws IOException {

        RandomAccessFile fromFile = new RandomAccessFile("/Users/shifulong/monitor_contact.sql", "rw");
        FileChannel fromChannel = fromFile.getChannel();

        RandomAccessFile toFile = new RandomAccessFile("/Users/shifulong/monitor_contact_to.sql", "rw");
        FileChannel toChannel = toFile.getChannel();

        long position = 0;
        fromChannel.transferTo(position,toChannel.size(),toChannel);
        fromChannel.close();
        toChannel.close();
    }

 

selector

Selector selector = Selector.open();
SelectableChannel channel = null;// TODO
channel.configureBlocking(false);//非阻塞模式

//channel注册selector,第二个参数是intreast事件,多个intreast事件可以用“|”
//  int intreastSetP = SelectionKey.OP_ACCEPT | SelectionKey.OP_READ;
SelectionKey selectionKey1 = channel.register(selector, SelectionKey.OP_READ);

int intreastSet = selectionKey1.interestOps();

int readySet = selectionKey1.readyOps();

//添加附加对象
selectionKey1.attach(new Object());
//取出附加对象
selectionKey1.attachment();

//选取通道
selector.select();//block when at least a ready channel that you regist
selector.select(1000);//timeout
selector.selectNow();//return immediately

Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
    SelectionKey selectionKey = iterator.next();
    if (selectionKey.isAcceptable()) {
        // 这两个含义不太清楚
    } else if (selectionKey.isConnectable()) {
        // 这两个含义不太清楚
    } else if (selectionKey.isReadable()) {
        // a channel is ready for reading
    } else if (selectionKey.isWritable()) {
        // a channel is ready for writing
    }
    iterator.remove();

    SelectableChannel selectableChannel = selectionKey.channel();
} 
whole demo
public void selectTest() throws IOException {
    Selector selector = Selector.open();
    SelectableChannel channel = null;
    channel.register(selector, SelectionKey.OP_READ);
    while (true) {
        int readyChannels = selector.select();
        if (readyChannels == 0) continue;
        Set<SelectionKey> selectedKeys = selector.selectedKeys();
        Iterator<SelectionKey> iteratror = selectedKeys.iterator();
        while (iteratror.hasNext()) {
            SelectionKey selectionKey = iteratror.next();
            if (selectionKey.isReadable()) {
                // TODO
            }
            iteratror.remove();
        }
    }
}
 

 pipe

//两个线程的单向数据连接
public void pipePractice() throws IOException {
    Pipe pipe = Pipe.open();
    Pipe.SinkChannel sinkChannel = pipe.sink();
    writeToSonk();

    Pipe.SourceChannel sourceChannel = pipe.source();
    readFromSource();

}
private void readFromSource() {
    // TODO
}
private void writeToSonk() {
    // TODO
}

 

 

 

 

猜你喜欢

转载自shifulong.iteye.com/blog/2255045