Java 范例 - 字节处理
前言
Java 编程中常会遇到需要进行字节处理的地方,本篇文章就来探讨编程中会遇到的字节处理问题。
字节序
字节序(endianness)是对于多字节数据来说的,它描述了多字节数据存储的顺序,分为大端字节序(big endian)和小端字节序(little endian)两种。
大端序即高位字节位于低地址,而小端字节序则与之相反。例如 4 字节的数据 0x01234567
,其 大、小端字节序存储顺序如下。
Big Endian
address |0x100|0x101|0x102|0x103|
content |01 |23 |45 |67 |
Little Endian
address |0x100|0x101|0x102|0x103|
content |67 |45 |23 |01 |
为保证数据在不同设备进行传输时能被正确解析,规定了使用大端字节序作为网络字节序。
字节序转换
由于 Java 使用大端字节序在内存中进行数据存储,所以进行网络传输时不需要进行字节序转换。不过除了网络编程,还是有需要小端字节序的情况,下面就来讨论如何进行字节序的转换。
基本类型字节数
下表给出了 Java 八种基本类型的所占的字节数,可以看到里面六种类型都是多字节的,而这六种在转换时都是需要处理的。
类型 | 字节数 |
---|---|
byte | 1 |
boolean | 1 |
char | 2 |
short | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
这里需要强调一点,基本类型的数组形式虽是多字节的,但其字节序只和数组元素有关,而与数组元素的顺序无关。例如存在短整形数组 {0x0001, 0x0002}
(Java 默认的大端字节序),则其小端字节序是 {0x0100, 0x0200}
。
字节缓冲区
字节缓冲区(ByteBuffer)常用于数据的字节级处理,可以利用静态方法 ByteBuffer allocate(int)
来申请一块固定大小的缓冲区,或者使用 ByteBuffer wrap(byte[])
包装一个现有的字节数组。
字节缓冲区提供了 void order(ByteOrder)
方法来设置该字节缓冲区的字节序,提供了 asTypeBuffer()
(其中 Type 为多字节的基本类型)来将字节缓冲区作为其他基本类型缓冲区,以便于插入其他基本类型,利用这些特性便可实现基本类型的字节序转换。
基本类型及其数组的字节序转换
下面例子利用了字节缓冲区来进行整型的字节序转换,而只需将 asIntBuffer()
改成相应基本类型的 asTypeBuffer()
方法,就可以进行其它基本类型的字节序转换。
int data = 0x01020304;
ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES);
buf.asIntBuffer().put(data);
// [1, 2, 3, 4]
System.out.println(Arrays.toString(buf.array()));
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.asIntBuffer().put(data);
// [4, 3, 2, 1]
System.out.println(Arrays.toString(buf.array()));
对于基本类型的数组,只需将 data
数据改成数组即可,如下面给出的例子。
int[] data = new int[]{0x01020304, 0x05060708};
ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES * data.length);
buf.asIntBuffer().put(data);
// [1, 2, 3, 4, 5, 6, 7, 8]
System.out.println(Arrays.toString(buf.array()));
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.asIntBuffer().put(data);
// [4, 3, 2, 1, 8, 7, 6, 5]
System.out.println(Arrays.toString(buf.array()));
字符串的字节序转换
Java 中字符类型使用 Unicode
字符集,所以占用两个字节,而字符串只需要将其转成字符数组即可进行字节序转换。
char[] data = new String("example").toCharArray();
ByteBuffer buf = ByteBuffer.allocate(Character.BYTES * data.length);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.asCharBuffer().put(data);
字符串编码与字节数组
编程中通常需要将字符串转字节数组,而这就涉及到字符串编解码,但 Java 提供了很便捷的方式来进行转换,所以无需关心如何字符串编解码。
byte[] buf = new String("example").getBytes(); // use platform's default charset
注意上面使用了平台的默认的字符集(可利用 Charset.defaultCharset()
获取平台默认字符集)进行解码,而不是上面提到的 Unicode
字符集,但可以如下面例子一样指定字符集。
byte[] buf = new String("example").getBytes("UTF-8"); // use specify charset 'UTF-8'
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统