我有一个字节缓冲区,并希望有指向第一个元素的标识符,该元素不必是数组本身的第一个元素。
private void uint32ToBuffer(int val, byte[] buffer)
{
buffer[0] = (byte)val;
buffer[1] = (byte)(val >>> 8);
buffer[2] = (byte)(val >>> 16);
buffer[3] = (byte)(val >>> 24);
}
我想做
byte[] buffer = new byte[512];
uint32ToBuffer(3, &buffer[2]);
但显然它不起作用。是否有可能在不让函数
uint32ToBuffer
知道它应该写入数组的初始位置以从 C
类似语言复制指针算术逻辑的情况下以某种方式执行此操作?
没有。
您有几个选择:
java.nio.buffer.ByteBuffer
ByteBuffer是一个抽象的概念;它们很像数组,因为它们是固定大小并代表字节。与
byte[]
不同,它有一个有意义的 API,与 byte[]
不同,它已经在跟踪中烘焙(例如,它有一个“位置”,不像字节数组只有一个长度)。事实上,非常棒的跟踪,带有标记、重置和限制。实际上,字节缓冲区由“围绕包含数据的数组的轻型对象包装器”或“直接访问内存映射 I/O 事物”组成。
事实上,ByteBuffer 已经具有 write-int-to-byte-array-as-little-endian 功能!
byte[] buffer = new byte[512];
ByteBuffer bb = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN);
bb.position(2);
bb.putInt(3);
此时不再需要
uint32ToBuffer
方法; bytebuffer 已经有了它。 putInt(3)
电话:
[2]
、[3]
、[4]
和[5]
的字节中(因为bb的位置是'2';它是相对写入)。具体写成3/0/0/0是因为buffer对象的字节序是LITTLE_ENDIAN
。默认情况下,它们是大端字节序,并且会写入 0/0/0/3。不知道你为什么要小端,这是一个非常过时的概念,只有 x86/x64 芯片仍在使用它:互联网往往是大端,而此时更受欢迎的 ARM 芯片也.如果您正在设计协议,我强烈建议您改写为大端。还有绝对写法:
bb.putInt(2, 3);
这具有相同的效果(将
3
写入 buffer[2]
,并将 0
写入 buffer[3]
到 buffer[5]
),但不依赖于缓冲区的位置值,也不对其进行修改。
我强烈建议您在这里使用它,对于您正在做的所有其他涉及“将小端字节序写入字节数组”的操作。 ByteBuffer API 可能包含您目前正在为其编写的实用方法的所有内容。
或者,传递位置;这在 Java API 中非常常见:
private void uint32ToBuffer(int val, byte[] buffer, int pos) {
buffer[pos] = (byte)val;
buffer[pos + 1] = (byte)(val >>> 8);
buffer[pos + 2] = (byte)(val >>> 16);
buffer[pos + 3] = (byte)(val >>> 24);
}
// ... and if you want, for convenience:
private void uint32ToBuffer(int val, byte[] buffer) {
uint32ToBuffer(val, buffer, 0);
}
Java 中没有办法创建作为其他数组的子切片的数组; array 非常基础,完全不支持任何可能算作“花哨”的东西。 Java 也没有任何类型的指针算法,因此,将 2 个插槽指向字节数组的引用根本不是问题。在 C 语言中,字节数组本质上“只是一个指针”,你不知道它有多长。在 java 中,因为缓冲区溢出是一个相当普遍的安全问题,所以这个概念不以任何方式存在,这是故意的。字节数组确实是它们自己的数据结构,特别是知道它们实际上是一个字节数组,以及它们有多长。 Java 使得不可能(除非你写一些被黑的类文件和 禁用 JVM 的类验证器)来编程缓冲区溢出问题。为此,指针 cannot 以这种方式修改(您不能在 java 中将指针“加 2”)。
只需使用 ByteBuffer 类及其支持方法。
ByteBuffer
ByteBuffer b = ByteBuffer.allocate(10);
uint32ToBuffer(3, b.position(2));
System.out.println(Arrays.toString(b.array()));
版画
[0, 0, 3, 0, 0, 0, 0, 0, 0, 0]
方法
private static void uint32ToBuffer(int val, ByteBuffer buffer){
buffer.put((byte)val);
buffer.put((byte)(val >>> 8));
buffer.put((byte)(val >>> 16));
buffer.put((byte)(val >>> 24));
};