0%

java | bytebuf 组成、写入、读取

bytebuf 的结构。

bytebuff 的结构如下 java | bytebuffer 用法

bytebuf 有 4 个部分组成

  • 写指针
  • 读指针
  • 容量
  • 最大容量

写入

方法 含义 备注
writeBoolean(Boolean value) 写入 boolean 用一字节 01 代表 true,00 代表 false
writeByte(int value) 写入 Byte
writeShort(int value)
writeInt(int value) 大端写入,0x250,即 00 00 02 50
writeIntLE(int value) 小端写入,0x250,即 50 02 00 00
writeBytes(ByteBuff value)
int writeCharSequence(CharSequence sequence,Charset charset) 写入字符串

代码

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
package com.redisc;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
import static io.netty.util.internal.StringUtil.NEWLINE;


@Slf4j
public class Run {

public static void main(String[] args) throws IOException {
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.directBuffer(); // 默认长度 256
byteBuf.writeBytes(new byte[]{1,2,3,4});
log(byteBuf);
byteBuf.writeInt(5); // 4 个字节
log(byteBuf);
}

private static void log(ByteBuf buffer){
int length=buffer.readableBytes();
int rows=length/16+(length%15==0?0:1)+4;
StringBuilder buf=new StringBuilder(rows*80*2)
.append("read index:").append(buffer.readerIndex())
.append(" write index:").append(buffer.writerIndex())
.append(" capacity:").append(buffer.capacity())
.append(NEWLINE);
appendPrettyHexDump(buf,buffer);
System.out.println(buf.toString());
}
}

输出

1
2
3
4
5
6
7
8
9
10
11
12
read index:0 write index:4 capacity:256
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02 03 04 |.... |
+--------+-------------------------------------------------+----------------+
read index:0 write index:8 capacity:256
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02 03 04 00 00 00 05 |........ |
+--------+-------------------------------------------------+----------------+

还有一类方法,是 set 开头的,可以写入数据,但是,不会改变指针位置。

扩容

  • 写入数据的大小未超过 512,则选择下一个 16 的整数倍,例如写入后大小为 12,则扩容后容量为 16
  • 写入后数据大小超过 512,则下一个为 2^n,例如,写入后大小为 513,则扩容为 2^10 = 10242^9 = 512
  • 扩容不能超过 max capacity,否则会报错

读取

读过的部分就是废弃的部分,再读只能读未读取的部分。

bytebuf.readByte() 读取一个字节

具体的代码如下

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
39
40
41
42
43
44
45
46
47
48
package com.redisc;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
import static io.netty.util.internal.StringUtil.NEWLINE;


@Slf4j
public class Run {

public static void main(String[] args) throws IOException {
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.directBuffer(); // 默认长度 256
byteBuf.writeBytes(new byte[]{1,2,3,4});
log(byteBuf);
byteBuf.writeInt(5); // 4 个字节
log(byteBuf);

System.out.println(byteBuf.readByte());
System.out.println(byteBuf.readByte());
System.out.println(byteBuf.readByte());
System.out.println(byteBuf.readByte());
log(byteBuf);

byteBuf.markReaderIndex(); // 标记一个指针
System.out.println(byteBuf.readInt());
log(byteBuf);

byteBuf.resetReaderIndex(); //将读指针返回 mark
log(byteBuf);
}

private static void log(ByteBuf buffer){
int length=buffer.readableBytes();
int rows=length/16+(length%15==0?0:1)+4;
StringBuilder buf=new StringBuilder(rows*80*2)
.append("read index:").append(buffer.readerIndex())
.append(" write index:").append(buffer.writerIndex())
.append(" capacity:").append(buffer.capacity())
.append(NEWLINE);
appendPrettyHexDump(buf,buffer);
System.out.println(buf.toString());
}
}

输出

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
read index:0 write index:4 capacity:256
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02 03 04 |.... |
+--------+-------------------------------------------------+----------------+
read index:0 write index:8 capacity:256
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02 03 04 00 00 00 05 |........ |
+--------+-------------------------------------------------+----------------+
1
2
3
4
read index:4 write index:8 capacity:256
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 00 00 05 |.... |
+--------+-------------------------------------------------+----------------+
5
read index:8 write index:8 capacity:256

read index:4 write index:8 capacity:256
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 00 00 05 |.... |
+--------+-------------------------------------------------+----------------+

还有一部分方法是 get 开头的,这个不改变指针。

请我喝杯咖啡吧~