首页 > 图灵资讯 > 技术篇>正文

Java NIO系列教程(三) Buffer(转)

2023-04-20 17:02:19

  Java NIO中的buffer用于与NIO通道互动。如你所知,数据从通道读入缓冲区,从缓冲区写入通道。

  缓冲区本质上是一个内存,可以写入数据,然后读取数据。这个内存被包装成NIO buffer对象提供了一组方法,方便访问该内存。

  以下是NIO 与buffer相关的话题列表:Buffer的基本用法 buffercapacity,position和limit buffer类型 Buffer的分配 在buffer中写数据 flip()方法 从buffer中读取数据 clear()compact()方法 mark()和reset()方法 equals()compareto()方法 Buffer的基本用法

  使用buffer读写数据一般遵循以下四个步骤: 将数据写入Buffer 调用flip()方法 从buffer中读取数据 调用clear()方法或者compact()方法

  当将数据写入buffer时,bufffer将记录多少数据。一旦要读取数据,就需要通过flip()将buffer从写作模式切换到读取模式。在阅读模式下,可以读取之前写入buffer的所有数据。

  一旦读完所有数据,就需要清空缓冲区,这样才能再次写入。清空缓冲区有两种方法:调用clear()或compact()。clear()方法将清空整个缓冲区。compact()方法只会清除已读数据。任何未读数据都会移动到缓冲区的起点,新写入的数据会放在缓冲区未读数据的后面。

  以下是使用buffer的例子: 01Randomacesfile aFile = new RandomAccessFile("data/nio-data.txt", "rw");Channel202File inChannel = aFile.getChannel();03 04//create buffer with capacity of 48 Bufferbytes05Byte buf = ByteBuffer.allocate(48);06 07int bytesRead = inChannel.read(buf); //read into buffer.08while (bytesRead != -1) {09 10 buf.flip(); //make buffer ready for read11 12 while(buf.hasRemaining()){13 System.out.print((char) buf.get()); // read 1 byte at a time14 }15 16 buf.clear(); //make buffer ready for writing17 bytesRead = inChannel.read(buf);18..close(); buffercapacity,position和limit

  缓冲区本质上是一个内存,可以写入数据,然后读取数据。这个内存被包装成NIO buffer对象提供了一组方法,方便访问该内存。

  要了解buffer的工作原理,需要熟悉其三个属性: capacity position limit

  position和limit的含义取决于buffer的阅读模式或写作模式。无论buffer处于什么模式,capacity的含义总是一样的。

  这里有一个关于读写模式中capacity、position和limit的解释,详细解释在插图后面。

Java NIO系列教程(三) Buffer(转)_ci

capacity

  Buffer作为一个内存块,有一个固定的大小值,也称为“capacity”.你只能写capacityby、long,char等类型。一旦buffer满了,就需要清空它(通过阅读数据或清除数据),然后继续写数据来写数据。position

  当您将数据写入buffer时,position表示当前位置。最初的position值为0。当一个byter时、buffer写下long等数据后, position将向前移动到下一个可插入数据的bufer单元。position最大可以是capacity – 1.

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

  在写作模式下,buffer的limit表示您最多可以在buffer中写多少数据。 在写作模式下,limit等于buffer的capacity。

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

  Java NIO 以下Buffer类型 ByteBuffer MappedByteBuffer CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer

  p<> 正如你所看到的,这些buffer类型代表不同的数据类型。换句话说,它可以通过char,short,int,long,float 或 缓冲区内的字节由double类型操作。

  MappedByteBuffer 有些特别的,在涉及它的特别章节中。Buffer的分配

  要想获得buffer对象,首先要分配。 每个buffer类都有一个allocate方法。以下是Bytebuffer分配48字节capacity的例子。 ByteBuffer buf = ByteBuffer.allocate(48);

  这是Charbuffer,可以存储1024个字符: 1charbuffer buf = CharBuffer.allocate(1024); 在buffer中写数据

  将数据写到buffer有两种方式: 从Channel到buffer。 buffer的put()方法写入buffer。

  从Channel到Buffer的例子 int bytesRead = inChannel.read(buf); //read into buffer.

  Buffer的例子是通过put写的: buf.put(127);

  put方法有很多版本,允许您以不同的方式将数据写入bufer。例如, 写一个指定的位置,或者在buffer中写一个字节数组。 Buffer实现的更多细节参考Javadoc。flip()方法

  flip方法将buffer从写作模式切换到读取模式。调用flip()方法将position设置为0,并将limit设置为之前position的值。

  换句话说,position现在用来标记阅读位置,limit说之前写了多少byte、char等 —— 现在能读多少byte?、char等。从buffer中读取数据

  有两种方法可以从buffer中读取数据: 从buffer读取数据到channel。 使用get()方法从buffer中读取数据。

  从Buffer读取数据到Channel的例子: 1//read from buffer into channel.2int bytesWritten = inChannel.write(buf);

  使用get()方法从buffer中读取数据的例子 byte aByte = buf.get();

  获取方法有很多版本,允许你以不同的方式从buffer中读取数据。比如从指定的position读取,或者从buffer读取数据到字节数组。有关buffer实现的更多细节,请参考Javadoc。rewind()方法

  Buffer.rewind()将position设置为0,因此您可以重读buffer中的所有数据。limit保持不变,仍然表示您可以从buffer中读取多少元素(byte、char等。).clear()compact()方法

  一旦阅读了buffer中的数据,就需要准备好buffer再次写入。可以通过clear()或compact()来完成。

  如果调用clear()方法,position将设置为0,limit将设置为 capacity的价值。换句话说,Buffer 它被清空了。buffer中的数据没有被清除,但这些标记告诉我们可以从哪里开始将数据写入buffer。

  如果buffer中有一些未读数据,并调用clear()方法,数据将被“遗忘”,这意味着没有标记会告诉你读过哪些数据,哪些数据还没有读过。

  如果buffer中仍有未读数据,并且后续需要这些数据,但此时想先写一些数据,则使用compact()方法。

  compact()方法将所有未读数据复制到buffer的起点。然后将position设置在最后一个未读元素的正后面。limit属性仍然像clear()方法一样设置为capacity。现在buffer已经准备好写数据了,但不会覆盖未读数据。mark()和reset()方法

  通过调用bufferer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用bufferer.reset()方法恢复到这个position。例如: buffer.mark();//call buffer.get() a couple of times, e.g. during parsing.buffer.reset(); //set position back to mark. equals()compareto()方法

  两个buffer可以使用equals()和compareto()。equals()

  当满足以下条件时,表示两个buffer相等: 类型相同(byte、char、int等。). buffer中剩余的byter、char等数量相等。 buffer中所有剩余的byter、char等都一样。

  正如你所看到的,equals只是比较buffer的一部分,并不是每个元素都比较。事实上,它只比较buffer中的剩余元素。compareTo()方法

  compareTo()比较两个buffer的剩余元素的方法(byte、char等), 如果满足以下条件,则认为一个buffer“小于”另一个buffer: 第一个不相等的元素小于另一个buffer中对应的元素 。 所有元素都是相等的,但是第一个buffer比另一个先耗尽(第一个buffer的元素比另一个少)。

  (译注:剩余元素来源于 position与limit之间的元素)

上一篇 Java高效读取大文件(转)
下一篇 docker 部署minio

文章素材均来源于网络,如有侵权,请联系管理员删除。