在字节数组中增加一个计数器

Increment a counter inside a byte array

我有一个 5 字节的数组(固定长度)。前 21 位代表一个计数器,其余 19 位代表一些 id。我需要将计数器加一。我该怎么做?

我不确定我是否解决了您的问题。由于没有详细描述内存布局,我假设了一个布局。您可以获取计数器,将其加 1,然后设置计数器。如果布局符合要求,则需要对其进行全面测试。我不是在处理数据溢出的情况,你可能需要添加一些限制。

public class Test {
    public static void main(String[] args) {
        byte[] bytes = new byte[5];
        bytes[2] = 5;
        for (int i = 0; i <= 0x1fffff; i++) {
            setCount(bytes, i);
            if (getCount(bytes) != i) {
                System.out.println(i);
                debug(bytes);
            }
        }
    }

    public static int getCount(byte[] bytes) {
        return ((bytes[2] >> 3) & 0x1f) + ((bytes[1] << 5) & 0x1fff) + ((bytes[0] << 13) & 0x1fffff);
    }

    public static void setCount(byte[] bytes, int count) {
        bytes[0] = (byte) (count >> 13 & 0xff);
        bytes[1] = (byte) (count >> 5 & 0xff);
        bytes[2] = (byte) ((bytes[2] & 0x7) + ((count & 0x1f) << 3));
    }

    public static void debug(byte[] bytes) {
        for (byte b : bytes) {
            for (int i = 7; i >= 0; i--) {
                System.out.print(b >> i & 1);
            }
            System.out.print(" ");
        }
        System.out.println();
        System.out.println("Count:" + getCount(bytes));
    }

    public static void printInt(int num) {
        for (int i = 31; i >= 0; i--) {
            System.out.print(num >> i & 1);
        }
        System.out.println();
    }
}

我不确定我是否解决了你的问题。

public class Main
{
    public static void main(String[] args)
    {
        //################
        //#  BIG ENDIAN  #
        //################
        
        //initial counter == 1 (b0000_0000_0000_0000_0000_1)
        //initial ids == 3 (b000_0000_0000_0000_0011)
        byte[] array = { 0, 0, 8, 0, 3 };
        int counter = ((array[0] & 0xFF) << 13)
            | ((array[1] & 0xFF) << 5)
            | ((array[2] & 0xF8) >> 3);
        System.out.println(counter); //1
        ++counter;
        System.out.println(counter); //2
        //Repack the counter into the array.
        array[0] = (byte)((counter & 0x1FE000) >> 13);
        array[1] = (byte)((counter & 0x1FE0) >> 5);
        array[2] = (byte)(((counter & 0x1F) << 3)| (array[2] & 0x7));
        System.out.println(Arrays.toString(array)); //[0, 0, 16, 0, 3]
        //Retry & Verify
        counter = ((array[0] & 0xFF) << 13) //Same as above. Nothing is changed.
            | ((array[1] & 0xFF) << 5)
            | ((array[2] & 0xF8) >> 3);
        System.out.println(counter); //2
        ++counter;
        System.out.println(counter); //3
        
        //###################
        //#  LITTLE ENDIAN  #
        //###################
        
        //initial ids == 3 (b0000_0000_0000_0000_011)
        //initial counter == 1 (b0_0000_0000_0000_0000_0001)
        byte[] arr = { 0, 0, 96, 0, 1 };
        counter = ((arr[2] & 0x1F) << 16)
            | ((arr[3] & 0xFF) << 8)
            | (arr[4] & 0xFF);
        System.out.println(counter); //1
        ++counter;
        System.out.println(counter); //2
        //Repack the counter into the array.
        arr[2] = (byte)((arr[2] & 0xE0)  | ((counter & 0x1F0000) >> 16));
        arr[3] = (byte)((counter & 0xFF00) >> 8);
        arr[4] = (byte)(counter & 0xFF);
        System.out.println(Arrays.toString(arr)); //[0, 0, 96, 0, 2]
        //Retry & Verify
        counter = ((arr[2] & 0x1F) << 16) //Same as above. Nothing is changed.
            | ((arr[3] & 0xFF) << 8)
            | (arr[4] & 0xFF);
        System.out.println(counter); //2
        ++counter;
        System.out.println(counter); //3
    }
    
}

这个答案是基于我从 OP 的评论中了解到的内存布局:

array[0]: bits 0..7 are counter bits 0..7 (lsb)
array[1]: bits 0..7 are counter bits 8..15
array[2]: bits 0..4 are counter bits 16..20 (msb)
          bits 5..7 are part of the id
array[3]: bits 0..7 are part of the id
array[3]: bits 0..7 are part of the id

然后

int byte0 = (int) array[0] & 0xff;
int byte1 = (int) array[1] & 0xff;
int byte2 = (int) array[2] & 0x1f;

int count = byte0 | (byte1 << 8) | (byte2 << 16);

count = (count+1) & 0x1fffff;

array[0] = (byte) (count & 0x0000ff);
array[1] = (byte) ((count & 0x00ff00) >> 8);
array[2] = (array[2] & 0xe0) | (byte) ((count & 0x1f0000) >> 16);

应该可以解决问题。