IoBuffer和ByteBuffer

最近在做通信和传输的项目,大量的使用NIOMina,虽然之前一直对这部分比较关注,但是还没有好好的总结一下这方面的内容。今天想写点儿NIO里最基本的一个类ByteBuffer。至于Mina中的IoBuffer,我们可以先看Mina API中的描述:

A byte buffer used by MINA applications. This is a replacement for ByteBuffer. Please refer to ByteBuffer documentation for preliminary usage

当然,接下去也有写到:MINA does not use NIO ByteBuffer directly for two reasons,至于这Two Reasons,我们将在后面的比较中展开。

ByteBuffer继承了Buffer,对Buffer的理解可以说是NIO的入门。在Buffer中有4个重要的Attributes

Capacity: the capacity is set when the buffer is created and can never be changed

Limit: the first element of the buffer that should not be read or written

Position: the index of the next element to be read or written

Mark: a remembered position. Calling mark() set mark=position

他们的关系如下:0<=mark<=position<=limit<=capacity。


通俗的讲:

Capacity:开的内存的大小,一旦设定了,就不能更改了。注意,这里指的是原生的NIO

Limit:可以分读写来统计。在写入buffer时,limit表示有多少空间可以写入。在从buffer写出时,limit表示有多少可以写出。

Position:下一个要被读或写的位置。

Mark:标记位,可以记住某个position,方便后续操作。

 

对于ByteBuffer有如下常用的操作:

flip()::读写模式的转换。

rewind() :将 position 重置为 0 ,一般用于重复读。

clear() :清空 buffer ,准备再次被写入 (position 变成 0 , limit 变成 capacity) 。

compact(): 将未读取的数据拷贝到 buffer 的头部位。

mark() 、 reset():mark 可以标记一个位置, reset 可以重置到该位置。

get()getShort()等一系列get操作:获取ByteBuffer中的内容,当然这里get的内容都是从position开始的,所以要时刻注意position。每次get之后position都会改变。Position的变化是根据你get的类型,如果是short,那就是2byte,如果是int,那就是增加4byte,即32

put()putShort()等一系列put操作:向ByteBuffer添加内容,这里put的内容都是从position开始的。每次put之后position都会改变。

当然还有allocatehasRemaining等常用的方法,不过这些用法一般都不会出错,使用起来和4attributes也没有多大相关。特别注意:Buffers are not thread-safe. If you want to access a given buffer concurrently from multiple threads, you will need to do your own synchronization prior to accessing the buffer.至于Buffer或者ByteBuffer有什么用?那太多了,只要涉及到传输、涉及到通信,都可以用到。当然你也可以用它最原始的含义,缓冲。

 

好了NIOByteBuffer告一段落,接下来先说IoBuffer中说不用ByteBufferTwo Reasons

l  It doesn't provide useful getters and putters such as fill, get/putString, and get/putAsciiInt() enough.

l  It is difficult to write variable-length data due to its fixed capacity

看好了,对于第一点我想也没什么,增加了更实用的getString。关键是第二点,IoBuffer实现了Auto ExpandAuto Shrink。这就意味了,capacity可以根据传输内容的大小自动变更了。在使用上,我们可以这样写:

?
1
IoBuffer buf = IoBuffer.allocate( 1024 ).setAutoExpand( true );
在  IoBuffer 的源码中,大部分都使用了原生的  ByteBuffer 来实现,这部分采用  allocator 来实现。


?
1
2
/** The allocator used to create new buffers */
private static IoBufferAllocator allocator = new SimpleBufferAllocator();
在SimpleBufferAllocator的其中一段allocate:



?
1
2
3
4
5
6
7
8
9
public ByteBuffer allocateNioBuffer( int capacity, boolean direct) {
         ByteBuffer nioBuffer;
         if (direct) {
             nioBuffer = ByteBuffer.allocateDirect(capacity);
         } else {
             nioBuffer = ByteBuffer.allocate(capacity);
         }
         return nioBuffer;
     }
至于其他操作,和   ByteBuffer   类似。

贴一段Reilly - Java NIO中的一段代码作为结束,后续更多的Mina相关会根据开发进度给出介绍:



?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.nio.CharBuffer;
  
public class BufferFillDrain {
private static int index = 0 ;
private static String[] strings = { "A random string value" ,
"The product of an infinite number of monkeys" ,
"Hey hey we're the Monkees" };
  
private static boolean fillBuffer(CharBuffer buffer) {
  
if (index >= strings.length) {
return false ;
}
String string = strings[index++];
  
for ( int i = 0 ; i < string.length(); i++) {
buffer.put(string.charAt(i));
}
return true ;
}
  
private static void drainBuffer(CharBuffer buffer){
while (buffer.hasRemaining()){
System.out.println(buffer.get());
}
System.err.println( "" );
}
  
public static void main(String[] args) {
CharBuffer buffer=CharBuffer.allocate( 100 );
while (fillBuffer(buffer)){
buffer.flip();
drainBuffer(buffer);
buffer.clear();
}
  
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ByteBuffer 是 Java 中用于处理二进制数据的缓冲区类,它可以在缓冲区中存储不同类型的数据,如 byte、short、int、long、float、double 等。使用 ByteBuffer 可以方便地进行数据的读取和写入,并且可以设置字节序(Byte Order)来保证数据在不同机器上的正确性。 ByteBuffer 的常用方法包括: 1. allocate(int capacity):分配一个容量为 capacity 的 ByteBuffer。 2. put(byte[] src):将一个字节数组写入到 ByteBuffer 中。 3. get(byte[] dest):将 ByteBuffer 中的数据读取到一个字节数组中。 4. flip():将读写模式切换,将 limit 设置为当前位置,将 position 设置为 0。 5. rewind():将 position 设置为 0,使得数据可以重新读取。 6. clear():清空 ByteBuffer,将 position 设置为 0,将 limit 设置为 capacity。 例如,下面是一个使用 ByteBuffer 写入和读取数据的示例代码: ```java // 创建一个容量为 10 的 ByteBuffer ByteBuffer buffer = ByteBuffer.allocate(10); // 写入数据 buffer.putInt(123); buffer.putDouble(3.14); buffer.putChar('A'); // 切换到读模式 buffer.flip(); // 读取数据 int intValue = buffer.getInt(); double doubleValue = buffer.getDouble(); char charValue = buffer.getChar(); System.out.println(intValue); // 输出 123 System.out.println(doubleValue); // 输出 3.14 System.out.println(charValue); // 输出 A ``` 需要注意的是,ByteBuffer 中的 position、limit 和 capacity 属性的含义如下: 1. position:当前读写位置。 2. limit:缓冲区的限制,即当前可以读写的最大位置。 3. capacity:缓冲区的容量,即最多可以存储多少字节数据。 在写入数据时,position 会自动向前移动,而 limit 和 capacity 不会变化;在读取数据时,position 和 limit 会随着读取的数据量自动向前移动。如果需要重新读取数据,可以使用 rewind() 方法将 position 设置为 0,如果需要清空缓冲区,可以使用 clear() 方法将 position 设置为 0,limit 设置为 capacity。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值