Java ByteBuf解析和进制转换汇总
文章目录
- Java ByteBuf解析和进制转换汇总
- ByteBuf API详细介绍
- 1. 概述
- 2. 主要特点
- 3. 创建方式
- 4. 基本操作
- 5. 内存管理
- 6. 使用场景
- 7. 处理大端序/小端序
- 8. 调试工具Hex Dump
- Java进制转换介绍
- 1. 十进制转十六进制
- 2. 十六进制转十进制
- 3. 十六进制转Ascii码
- 4. 十进制的反码
- 5. 十六进制的反码
- 6. 十六进制转 byte[]数组
- 7. byte[]数组 转十六进制
- 8. String 转 ByteBuf
- 9. ByteBuf 转 String
- 10. byte[] 数组 转 String
- 11. byte b 转 Boolean
- 12. byte b 转 String
- 13. byte b 转 int
- 14. byte b 转十六进制
- 完整整合示例
- 场景描述
- 代码实现
- 注意事项
- 最后总结
Java ByteBuf解析和进制转换汇总
ByteBuf API详细介绍
1. 概述
ByteBuf
是 Netty 中对字节缓冲区的抽象,用于在网络应用中高效地处理数据读写操作。它提供了丰富的 API,让开发者可以方便地处理字节数据。
2. 主要特点
- 性能高效 :采用直接内存操作和内存池技术,减少内存拷贝,提高数据传输效率。
- 灵活的容量管理 :可以根据需要动态调整缓冲区容量,避免频繁的内存分配和释放。
- 读写操作分离 :通过读索引和写索引分离设计,方便进行读写操作,避免数据覆盖等问题。
- 丰富的 API :提供了多种读写方法,支持不同类型数据的转换和操作,方便开发者进行数据处理。
3. 创建方式
-
堆缓冲区(Heap ByteBuf) :通过
ByteBufAllocator
的heapBuffer()
方法创建,数据存储在 JVM 堆内存中,便于垃圾回收,适合频繁分配和释放的小型缓冲区。ByteBuf heapBuf = ByteBufAllocator.DEFAULT.heapBuffer(1024);
-
直接缓冲区(Direct ByteBuf) :通过
ByteBufAllocator
的directBuffer()
方法创建,数据存储在直接内存中,减少内存拷贝,适合大数据量传输,如频繁的 I/O 操作。ByteBuf directBuf = ByteBufAllocator.DEFAULT.directBuffer(1024);
-
复合缓冲区(Composite ByteBuf) :通过
ByteBufAllocator
的compositeBuffer()
方法创建,可以将多个ByteBuf
合并成一个逻辑缓冲区进行操作,方便对多个缓冲区的统一管理。ByteBuf compositeBuf = ByteBufAllocator.DEFAULT.compositeBuffer(); compositeBuf.addComponents(buf1, buf2, buf3);
4. 基本操作
-
写操作
-
写基本数据类型:提供了
writeXXX()
系列方法,如writeInt()
、writeLong()
、writeBytes()
等,用于将不同类型的数据写入缓冲区。ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(); buf.writeInt(123); buf.writeLong(4567890L); buf.writeBytes(new byte[]{1, 2, 3, 4});
-
写字符串:可以将字符串转换为字节数组后写入,或者使用
writeCharSequence()
方法指定字符编码写入。ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(); String str = "Hello, Netty!"; buf.writeBytes(str.getBytes(StandardCharsets.UTF_8)); // 或者 buf.writeCharSequence(str, StandardCharsets.UTF_8);
-
-
读操作
-
读基本数据类型:提供了
readXXX()
系列方法,如readInt()
、readLong()
、readBytes()
等,用于从缓冲区读取不同类型的数据。ByteBuf buf = ...; // 假设缓冲区中已写入数据 int num = buf.readInt(); long value = buf.readLong(); byte[] bytes = new byte[4]; buf.readBytes(bytes);
-
读字符串:可以先读取字节数组,然后转换为字符串,或者根据长度读取指定字符数的字符串。
ByteBuf buf = ...; // 假设缓冲区中已写入字符串数据 byte[] bytes = new byte[buf.readableBytes()]; buf.readBytes(bytes); String str = new String(bytes, StandardCharsets.UTF_8); // 或者 int length = buf.readInt(); // 假设前面存储了字符串长度 CharBuffer charBuffer = buf.readCharSequence(length, StandardCharsets.UTF_8); String str = charBuffer.toString();
-
-
容量管理
-
获取容量:使用
capacity()
方法获取缓冲区的当前容量。int capacity = buf.capacity();
-
调整容量:使用
capacity(int newCapacity)
方法调整缓冲区容量,新容量不能小于当前写索引。buf.capacity(2048); // 将容量调整为 2048
-
确保可写:使用
ensureWritable(int minWritableBytes)
方法确保缓冲区有足够的可写空间,如果没有,则自动调整容量。buf.ensureWritable(512); // 确保有 512 字节的可写空间
-
-
索引操作
-
获取读索引:使用
readerIndex()
方法获取当前读索引。int readerIndex = buf.readerIndex();
-
设置读索引:使用
readerIndex(int readerIndex)
方法设置读索引,但不能超过写索引。buf.readerIndex(10); // 将读索引设置为 10
-
获取写索引:使用
writerIndex()
方法获取当前写索引。int writerIndex = buf.writerIndex();
-
设置写索引:使用
writerIndex(int writerIndex)
方法设置写索引,但不能小于读索引且不能超过容量。buf.writerIndex(20); // 将写索引设置为 20
-
获取可读字节数:使用
readableBytes()
方法获取可读字节数,即写索引减去读索引。int readableBytes = buf.readableBytes();
-
获取可写字节数:使用
writableBytes()
方法获取可写字节数,即容量减去写索引。int writableBytes = buf.writableBytes();
-
5. 内存管理
-
引用计数 :
ByteBuf
支持引用计数机制,通过retain()
方法增加引用计数,release()
方法减少引用计数,当引用计数为 0 时,内存会被释放。ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(); buf.retain(); // 增加引用计数 // 使用缓冲区 buf.release(); // 减少引用计数,释放内存(如果引用计数为 0)
-
自动释放 :在 Netty 的 ChannelPipeline 中,通常会自动管理
ByteBuf
的生命周期,在处理完成后自动释放内存,但开发者也可以手动释放以确保内存及时回收。try {ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();// 使用缓冲区 } finally {buf.release(); // 确保释放内存 }
6. 使用场景
- 网络通信 :在 Netty 的网络应用中,
ByteBuf
是数据传输的核心载体,用于处理客户端和服务器之间的数据读写操作。 - 数据处理 :对二进制数据进行处理,如解析协议、构造消息等,
ByteBuf
提供了方便的 API 进行数据操作。 - 文件读写 :在进行文件读写操作时,可以使用
ByteBuf
作为缓冲区,提高读写效率。
7. 处理大端序/小端序
网络通信中需注意字节顺序(默认大端序),可通过 ByteBuf.order()
显式设置:
ByteBuf buf = Unpooled.buffer().order(ByteOrder.LITTLE_ENDIAN);
buf.writeInt(0x12345678); // 写入小端序的 int
8. 调试工具Hex Dump
使用 Netty 的 ByteBufUtil
快速打印二进制内容:
ByteBuf buf = Unpooled.wrappedBuffer(new byte[]{0x48, 0x65});
System.out.println(ByteBufUtil.hexDump(buf)); // 输出: 4865
通过合理使用 ByteBuf
API,包括ByteBufUtil工具类可以提高网络应用的性能和开发效率。在实际开发中,需要根据具体需求选择合适的创建方式和操作方法,注意内存管理以避免内存泄漏等问题。
Java进制转换介绍
概述
本文提供 Java 中进制转换、字节数组(byte[])与 Netty ByteBuf 的互操作示例,涵盖十进制、十六进制、ASCII 码、反码及基础数据类型转换等场景。
以下是一个包含 Java 技术文档进制转换结合 Bytes 数组和 ByteBuf 使用示例的 Demo
核心工具类
import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import java.nio.charset.StandardCharsets;
1. 十进制转十六进制
public class DecimalToHex {public static String decimalToHex(int decimal) {return Integer.toHexString(decimal).toUpperCase(); // 转为大写十六进制}public static void main(String[] args) {int decimal = 255;String hex = decimalToHex(decimal);System.out.println(decimal + " 的十六进制是:" + hex); // 输出: FF}
}
2. 十六进制转十进制
public class HexToDecimal {public static int hexToDecimal(String hex) {return Integer.parseInt(hex, 16);}public static void main(String[] args) {String hex = "FF";int decimal = hexToDecimal(hex);System.out.println(hex + " 的十进制是:" + decimal);}
}
3. 十六进制转Ascii码
public class HexToAscii {public static String hexToAscii(String hex) {StringBuilder sb = new StringBuilder();for (int i = 0; i < hex.length(); i += 2) {String str = hex.substring(i, i + 2);sb.append((char) Integer.parseInt(str, 16));}return sb.toString();}public static void main(String[] args) {String hex = "48656C6C6F";String ascii = hexToAscii(hex);System.out.println(hex + " 的Ascii码是:" + ascii);}
}
4. 十进制的反码
// demo1
public class DecimalOneComplement {public static String decimalOneComplement(int decimal) {String bin = Integer.toBinaryString(decimal);StringBuilder sb = new StringBuilder();for (char c : bin.toCharArray()) {sb.append(c == '0' ? '1' : '0');}return sb.toString();}public static void main(String[] args) {int decimal = 5;String oneComplement = decimalOneComplement(decimal);System.out.println(decimal + " 的反码是:" + oneComplement);}
}
// demo2
public static int decimalComplement(int num) {return ~num; // 按位取反
}// 示例
System.out.println(decimalComplement(5)); // 输出: -6
5. 十六进制的反码
// demo1
public class HexOneComplement {public static String hexOneComplement(String hex) {int decimal = Integer.parseInt(hex, 16);String bin = Integer.toBinaryString(decimal);StringBuilder sb = new StringBuilder();for (char c : bin.toCharArray()) {sb.append(c == '0' ? '1' : '0');}return sb.toString();}public static void main(String[] args) {String hex = "A3";String oneComplement = hexOneComplement(hex);System.out.println(hex + " 的反码是:" + oneComplement);}
}// demo2
public static String hexComplement(String hex) {int num = Integer.parseInt(hex, 16);return Integer.toHexString(~num).toUpperCase();
}// 示例
System.out.println(hexComplement("0A")); // 输出: F5
6. 十六进制转 byte[]数组
import java.util.Arrays;public class HexToByteArray {public static byte[] hexToByteArray(String hex) {int len = hex.length();byte[] data = new byte[len / 2];for (int i = 0; i < len; i += 2) {data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)+ Character.digit(hex.charAt(i + 1), 16));}return data;}public static void main(String[] args) {String hex = "48656C6C6F"; // "Hello"的十六进制byte[] bytes = hexToByteArray(hex);System.out.println("十六进制转byte数组:" + Arrays.toString(bytes));}
}
7. byte[]数组 转十六进制
import java.util.Arrays;public class ByteArrayToHex {public static String byteArrayToHex(byte[] bytes) {StringBuilder sb = new StringBuilder();for (byte b : bytes) {sb.append(String.format("%02X", b));}return sb.toString();}public static void main(String[] args) {// 示例//String hex = byteArrayToHex(new byte[]{0x48, 0x65, 0x6C, 0x6C, 0x6F}); // 输出: 48656C6C6Fbyte[] bytes = {72, 101, 108, 108, 111};String hex = byteArrayToHex(bytes);System.out.println("byte数组转十六进制:" + hex);}
}
8. String 转 ByteBuf
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;public class StringToByteBuf {public static ByteBuf stringToByteBuf(String str) {return ByteBufAllocator.DEFAULT.buffer().writeBytes(str.getBytes());}public static void main(String[] args) {String str = "Hello Netty";ByteBuf byteBuf = stringToByteBuf(str);System.out.println("String转ByteBuf:" + byteBuf);}
}
9. ByteBuf 转 String
import io.netty.buffer.ByteBuf;public class ByteBufToString {public static String byteBufToString(ByteBuf byteBuf) {byte[] bytes = new byte[byteBuf.readableBytes()];byteBuf.readBytes(bytes);return new String(bytes);}public static void main(String[] args) {ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();byteBuf.writeBytes("Hello Netty".getBytes());String str = byteBufToString(byteBuf);System.out.println("ByteBuf转String:" + str);}
}
10. byte[] 数组 转 String
public class ByteArrayToString {public static String byteArrayToString(byte[] bytes) {return new String(bytes);}public static void main(String[] args) {byte[] bytes = {72, 101, 108, 108, 111};String str = byteArrayToString(bytes);System.out.println("byte数组转String:" + str);}
}
11. byte b 转 Boolean
public class ByteToBoolean {public static Boolean byteToBoolean(byte b) {return b != 0;}public static void main(String[] args) {byte b = 1;Boolean bool = byteToBoolean(b);System.out.println("byte转Boolean:" + bool);}
}
12. byte b 转 String
public class ByteToString {public static String byteToString(byte b) {return String.valueOf(b);}public static void main(String[] args) {byte b = 65;String str = byteToString(b);System.out.println("byte转String:" + str);}
}
13. byte b 转 int
public class ByteToInt {public static int byteToInt(byte b) {// 处理符号位,转为无符号intreturn b & 0xFF;}public static void main(String[] args) {// 示例System.out.println(byteToInt((byte)0xFF)); // 输出: 255byte b = -1;int i = byteToInt(b);System.out.println("byte转int:" + i);}
}
14. byte b 转十六进制
public class ByteToHex {public static String byteToHex(byte b) {return String.format("%02X", b);}public static void main(String[] args) {// 示例//System.out.println(ByteToHex((byte)0x1A)); // 输出: 1Abyte b = 65;String hex = byteToHex(b);System.out.println("byte转十六进制:" + hex);}
}
完整整合示例
场景描述
实现一个简单的协议解析器:
- 接收十六进制字符串
"01FF48656C6C6F"
,其中01
表示版本号,FF
为状态码,48656C6C6F
为有效载荷(“Hello” 的 ASCII)。 - 解析后输出版本号(十进制)、状态码的反码(十六进制)、有效载荷的字符串。
代码实现
public class ProtocolParser {public static void main(String[] args) {String hexData = "01FF48656C6C6F";ByteBuf buf = Unpooled.wrappedBuffer(hexToBytes(hexData));// 1. 读取版本号(1字节,转十进制)int version = byteToInt(buf.readByte());System.out.println("Version: " + version); // 输出: 1// 2. 读取状态码(1字节,转十六进制反码)byte statusByte = buf.readByte();String statusHex = byteToHex(statusByte);String statusComplement = hexComplement(statusHex);System.out.println("Status Complement: " + statusComplement); // 输出: 00// 3. 读取有效载荷(剩余字节,转字符串)byte[] payload = new byte[buf.readableBytes()];buf.readBytes(payload);String message = bytesToString(payload);System.out.println("Message: " + message); // 输出: Hellobuf.release(); // 释放资源}// 复用之前的转换方法(hexToBytes, byteToInt, byteToHex, hexComplement, bytesToString)
}
注意事项
- 字节符号处理
Java 的byte
类型是有符号的(范围:-128~127),处理时需用& 0xFF
转为无符号整数。 - 编码一致性
String
与byte[]
转换时需统一字符集(如StandardCharsets.UTF_8
)。 - 内存释放
使用 Netty 的ByteBuf
时,若为池化或直接内存,需手动调用release()
防止内存泄漏。
最后总结
通过结合 Java 原生字节操作与 Netty 的 ByteBuf
,可高效实现复杂协议解析、数据转换等任务。关键点包括:
- 内存管理:区分堆内存/直接内存,及时释放资源。
- 编码一致性:统一字符集避免乱码。
- 性能优化:利用池化缓冲区和复用对象减少 GC。
- 调试支持:使用
ByteBufUtil
工具快速诊断二进制数据。