NIO基础

来源:互联网 发布:网络维护是什么职位 编辑:程序博客网 时间:2024/05/22 06:48

8.6学习心得

1. Channel

(1) 所有的 IO 在NIO 中都从一个Channel 开始。

(2)既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的,通道可以异步地读写。

(3)通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。从通道读取数据到缓冲区,从缓冲区写入数据到通道。

(4)Channel的实现

  • FileChannel 从文件中读写数据。

  • DatagramChannel 能通过UDP读写网络中的数据。

  • SocketChannel 能通过TCP读写网络中的数据。

  • ServerSocketChannel 可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

(5)使用FileChannel读取数据到Buffer中的示例

public static void main(String[] args) {        RandomAccessFile aFile = new RandomAccessFile("D://text.txt", "rw");        FileChannel incChannel = aFile.getChannel();        ByteBuffer buf = ByteBuffer.allocate(48);        int byteRead = incChannel.read(buf);        while(byteRead != -1){            System.out.println("Read:" + byteRead);            buf.flip();            while(buf.hasRemaining()){                System.out.println((char)buf.get());            }            buf.clear();            byteRead = incChannel.read(buf);        }        aFile.close();}

2. Buffer

(1)使用Buffer读写数据一般遵循以下四个步骤:

  • 写入数据到Buffer
  • 调用flip()方法
  • 从Buffer中读取数据
  • 调用clear()方法或者compact()方法

(2)一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式。

(3)有两种方式能清空缓冲区:调用clear()或compact()方法。 clear()方法会清空整个缓冲区。compact()方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区 未读数据的后面。

(4)Buffer 的 capacity, position 和 limit

  • capacity

作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”。你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。

  • position

当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer 后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1。

当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0。当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。

  • limit

在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。

当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前 写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)。

(5)要想获得一个Buffer对象首先要进行分配。 每一个Buffer类都有一个allocate方法。

ByteBuffer buf = ByteBuffer.allocate(48);//分配48字节capacity的ByteBufferCharBuffer buf = CharBuffer.allocate(1024);//分配一个可存储1024个字符的CharBuffer

(6)向 Buffer 中写数据

  • 通过Channel的read方法,将数据写到Buffer
int bytesRead = fileChannel.read(byteBuffer);
  • 通过Buffer自身的put()方法
byteBuffer.put(2);

(7)从 Buffer 中读取数据

  • 从Buffer读取数据到Channel

  • 使用Buffer的get()方法读取Buffer的数据

(8)Buffer.rewind()将position设回0

(9)通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position。

buffer.mark();  //call buffer.get() a couple of times, e.g. during parsingbuffer.reset();  //set position back to mark

3. Selector

(1)Selector的创建

通过调用Selector.open()方法创建一个Selector,如下:

Selector selector = Selector.open();

(2)为了将Channel和Selector配合使用,必须将channel注册到selector上。通过SelectableChannel.register()方法来实现,如下:

channel.configureBlocking(false);SelectionKey key = channel.register(selector,Selectionkey.OP_READ);

(3)与Selector一起使用时,Channel必须处于非阻塞模式下。这意味着不能将FileChannel与Selector一起使用,因为FileChannel不能切换到非阻塞模式。而套接字通道都可以。

(4)通过Selector监听Channel时对什么事件感兴趣。可以监听四种不同类型的事件:

  • Connect SelectionKey.OP_CONNECT
  • Accept SelectionKey.OP_ACCEPT
  • Read SelectionKey.OP_READ
  • Write SelectionKey.OP_WRITE

拓展:

(1)学习了Java中将图片转换成txt文件的方式。

(2)看完python后去看scala。