博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
3 Java NIO Buffer-翻译
阅读量:5885 次
发布时间:2019-06-19

本文共 4106 字,大约阅读时间需要 13 分钟。

Buffer是用来跟Channel进行交互的。正如你所知道的,数据都是从Channel读到Buffer中的,并从Buffer写入到Channel中的。

Buffer本质上是一块内存空间,你可以将数据写入到这里,并在之后读取它。这个内存块被包装成NIO Buffer对象,并提供了一系列的方法来方便对这个内存块数据的操作。

Buffer基本用法

使用Buffer来读写数据基本上按照以下几个步骤来进行。

  1. 将数据写入到Buffer
  2. 调用buffer.flip()方法。
  3. 从buffer中读取数据。
  4. 调用buffer.clear()或buffer.compact()方法。

当你向Buffer中写入数据时,buffer会跟踪有多少数据已经写入。当需要读取数据时,你需要buffer.flip()方法将buffer从写模式切换到读模式。在读模式中,你可以读取所有已经写入到Buffer中的数据。

当你已经读完buffer中的数据,你需要清空buffer来保证buffer能够再次被写。清空buffer有两种方法:clear()方法和compat()方法。clear()方法会清空所有的buffer中的数据,compat()方法只会清空已经读过的数据,所有没有读过的数据会放到buffer的最前面,新写入的数据会追加到未读数据的后面。

这是一个Buffer使用的简单例子,包括write,flip,read和clear方法。

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");FileChannel inChannel = aFile.getChannel();//create buffer with capacity of 48 bytesByteBuffer buf = ByteBuffer.allocate(48);int bytesRead = inChannel.read(buf); //read into buffer.while (bytesRead != -1) {  buf.flip();  //make buffer ready for read  while(buf.hasRemaining()){      System.out.print((char) buf.get()); // read 1 byte at a time  }  buf.clear(); //make buffer ready for writing  bytesRead = inChannel.read(buf);}aFile.close();复制代码

Buffer Capacity, Position and Limit

Buffer本质上是一个可以进行读写操作的内存区域。这块内存区域被包装成Java Buffer对象,它包含了一系列的方法来简化对内存数据块的操作。

一个Buffer包含三个主要属性必须要熟悉。

  • capacity
  • position
  • limit

position和limit所代表的意义跟Buffer的读写模式有关,capacity则跟读写模式无关。

下图说明的是capacity,position和limit在读写模式中所代表的意义。

Capacity

作为一个内存块,Buffer有固定的大小,叫做capacity。你最大只能写入capacity个bytes,longs,chars个数据到Buffer。一旦buffer满了,你必须清空它(从buffer中读取数据或调用clear方法)。

Position

当你向缓存中写入数据,position表示当前位置。初始的position为0,当一个byte,long等被写入到buffer中时,poistion会移动到下一个可写的数据单元。position的最大值为capacity-1。

从Buffer中读取数据也是从指定的position开始。当使用flip()方法将buffer的模式从写模式切换到读模式,position位置变为0。数据从position指定的位置开始读起,并移动到下一个可读的单元。

Limit

在写模式中,limit指定了有多少数据可以写入到buffer中。在写模式中,limit与capacity值相等。

当buffer切换到读模式时,limit指定了buffer中可读的数据的大小。因此,当buffer切换到读模式时,limit被设置为写模式时的position位置。换句话说,读的数据可达到写的数据一样。

Buffer类型

Java NIO中包含以下几种类型。

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

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

分配Buffer

在获得Buffer对象之前必须先分配。每一个Buffer类都有一个allcate()方法来实现。下面是一个ByteBuffer分配48个字节容量的buffer的例子。

ByteBuffer buf = ByteBuffer.allcate(48);复制代码

下面是一个CharBuffer分配1024个字符的例子:

CharBuffer buf = CharBuffer.allcate(1024);复制代码

向Buffer中写入数据

向Buffer中写入数据有两种方式: 1、通过Channel向Buffer中写入数据。 2、通过buffer.put()方法写入。 下面是一个通过Channel向Buffer中写入数据的例子。

int byteRead = inChannel.read(buf); // read into buffer复制代码

下面是一个通过Buffer的put()方法写入数据的例子:

buf.put(127);复制代码

put还有其他版本的方法。比方说,在指定的位置写入数据,向buffer中写入一个数组。更多实现细节参考JavaDoc。

flip()

flip()将buffer从写模式切换到读模式。调用flip()方法将position重置为0,并将limit设置为原来position原来的位置。

换句话说,position表示当前读的位置,limit表示目前可读的数据。

从Buffer中读取数据

从Buffer中读取数据有两种方式

  1. 将Buffer中的数据读入到Channel。
  2. 通过Buffer的get()方法读取。

下面是一个将数据从Buffer读取到Channel中的例子。

// read from buffer into channelint byteWritten = inChannel.write(buffer);复制代码

下面是一个通过Buffer的get方法读取数据的例子

byte aByte = buf.get();复制代码

get方法还有很多其他的版本。例如,从指定的位置开始读,从buffer中读取一个数组。更多实现细节参考JavaDoc。

rewind()方法

Buffer.rewind()方法将position重置为0,因此,可以从头开始读取Buffer中的数据。limit的值保持不变,仍然表示最多可读取的数据量。

clear()和compat()方法

一旦完成从Buffer中读取数据,需要让Buffer准备好再次写入,可以通过clear()方法和compat()方法来完成。

如果调用的是clear()方法,position会重置为0,并且limit重置为capacity的值。换句话说,Buffer被清空了。Buffer中的数据并没有被清空,只是这些标记告诉我们从哪里开始可以写入数据。

当Buffer中还剩下一些未读取的数据时调用了clear()方法,这些数据将会被忽略。这意味着不再有任何标记告诉我们哪些数据已经读取过了,哪些数据还未读取过。

如果Buffer中仍有未读的数据,且后续还需要这些数据,但是此时想要先先写些数据,那么使用compact()方法。

compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。

mark方法与reset方法

通过调用Buffer.mark()方法可以标记一个指定的位置。通过Buffer的reset()方法可以回到原来mark时的position位置,下面是一个例子:

buffer.mark();// call buffer.get() a couple of times. buffer.reset();复制代码

equals方法和compareTo方法

可以通过equals方法和compareTo方法来比较两个buffer。

equals方法

  1. 有相同的类型(byte、char、int等)。
  2. Buffer中剩余的byte、char等的个数相等。
  3. Buffer中所有剩余的byte、char等都相同。

正如你所见,equals仅比较了Buffer中的部分数据,而不是Buffer中的每一个元素。事实上,它仅仅比较了剩余的元素。

compareTo方法

compareTo()方法比较两个Buffer的剩余元素(byte、char等), 如果满足下列条件,则认为一个Buffer“小于”另一个Buffer:

  1. 第一个不相等的元素小于另一个Buffer中对应的元素 。
  2. 所有元素都相等,但第一个Buffer比另一个先耗尽(第一个Buffer的元素个数比另一个少)。

转载地址:http://emlix.baihongyu.com/

你可能感兴趣的文章
在Jenkins中配置运行远程shell命令
查看>>
代码杂记
查看>>
linux中防CC攻击两种实现方法(转)
查看>>
《Programming WPF》翻译 第9章 4.模板
查看>>
hdu2159
查看>>
Windows7+VS2012下OpenGL 4的环境配置
查看>>
Linux Kernel中断子系统来龙去脉浅析【转】
查看>>
Linux NFS服务器的安装与配置
查看>>
Ada boost学习
查看>>
Unity中SendMessage和Delegate效率比较
查看>>
Linux下EPoll通信模型简析
查看>>
react-native 制作购物车ShopCart
查看>>
Linux服务器 java生成的图片验证码乱码问题
查看>>
【转】QT中QDataStream中浮点数输出问题
查看>>
mongodb3.2配置文件yaml格式 详解
查看>>
Java游戏开发中怎样才能获得更快的FPS?
查看>>
spring aop 配置
查看>>
nginx正向代理
查看>>
cloudstack4.2.1无法删除网络的故障解决办法
查看>>
PHP - 日期时间的转换
查看>>