将 int 数组转换为字节数组,同时保持大小

Convert an int array to a byte array while maintaining the size

我有以下二维 int 数组:

int[][] array = new int[128][128];

这个二维数组只包含 zerosones。我想读取每一行并从其内容中创建一个 byte[] (字节数组)。例如,假设第一行是:0101111000111...101,由 128 个数字组成。我希望这一行是 128 位的 byte[](这意味着 16 个字节)。

将每一行转换为字节数组的最有效方法是什么? 请记住,维护尺寸 重要 。由于每行由 128 "bits" 组成,因此字节数组的大小应为 16 字节 (128/8)。

我考虑过如何做到这一点的一种方法是将每一行都变成一个 BigInteger,然后将其转换成字节数组,但不幸的是我无法产生正确的结果。我还尝试了 Whosebug 可用的其他一些选项,但均无济于事。例如 this 解决方案产生 512 的输出,我不明白为什么。

出于上述原因,我不认为这个 post 是重复的,因为各种问题和答案都没有考虑字节数组的大小及其与整数数组。

既然你知道数组总是 8 的倍数,那么你就可以通过位操作安全地将二进制转换为字节。

public byte getByte(int[][] array, int x, int y) {
    byte result = 0;
    for (int bit = 0; bit < 8; bit++)
        result += (byte)(array[x][y + bit] * (1 << bit));
    return result;
}

或者,正如@Andreas 指出的那样,最高有效位通常排在第一位。只需将 for 循环更改为:

result += (byte)(array[x][y + bit] * (128 >> bit));

这是一维数组的代码。您只需对二维数组的外部数组重复执行此操作即可。

int[] bits = {0,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1};
assert bits.length % 8 == 0;

byte[] bytes = new byte[bits.length / 8];
for (int i = 0; i < bytes.length; i++) {
    int b = 0;
    for (int j = 0; j < 8; j++)
        b = (b << 1) + bits[i * 8 + j];
    bytes[i] = (byte)b;
}

for (int i = 0; i < bytes.length; i++)
    System.out.printf("%02x ", bytes[i]); // prints: 5e 3d 
System.out.println();

这是比较常见的Most Significant Bit First
@AndrewWilliamson 的回答显示了 Least Significant Bit First.

的算法

您链接到的方法通过简单地考虑由 int 组成的四个单独字节将 int 转换为字节。

您需要的是一种在结果字节中设置各个位的方法。这可以通过检查输入数组中的 128 个值中的每一个是否为 0 或 1,并相应地设置输出数组中的相应位来完成。这可以对每一行独立完成。

这是一个显示转换过程并打印和比较结果的 MCVE:

import java.util.Random;

public class IntArrayToByteArray2D
{
    public static void main(String[] args)
    {
        int sizeX = 128;
        int sizeY = 128;
        int input[][] = new int[sizeX][sizeY];

        Random random = new Random(0);
        for (int x=0; x<sizeX; x++)
        {
            for (int y=0; y<sizeY; y++)
            {
                boolean b = random.nextBoolean();
                input[x][y] = b ? 1 : 0;
            }
        }

        System.out.println("Input: ");
        String inputString = createString(input);
        System.out.println(inputString);

        byte output[][] = convert(input);
        String outputString = createString(output);
        System.out.println(outputString);

        System.out.println(inputString.equals(outputString));
    }

    private static byte[][] convert(int input[][])
    {
        byte output[][] = new byte[input.length][];
        for (int i=0; i<input.length; i++)
        {
            output[i] = convert(input[i]);
        }
        return output;
    }

    private static byte[] convert(int input[])
    {
        // Check whether input.length is divisible by 8, if desired
        byte output[] = new byte[input.length >> 3];
        for (int i=0; i<output.length; i++)
        {
            for (int j=0; j<8; j++)
            {
                if (input[(i<<3)+j] != 0)
                {
                    output[i] |= (1 << j); 
                }
            }
        }
        return output;
    }

    private static String createString(int array[][])
    {
        StringBuilder sb = new StringBuilder();
        for (int x=0; x<array.length; x++)
        {
            for (int y=0; y<array[x].length; y++)
            {
                sb.append(array[x][y]);
            }
            sb.append("\n");
        }
        return sb.toString();
    }

    private static String createString(byte array[][])
    {
        StringBuilder sb = new StringBuilder();
        for (int x=0; x<array.length; x++)
        {
            for (int y=0; y<array[x].length; y++)
            {
                for (int b=0; b<8; b++)
                {
                    if ((array[x][y] & (1<<b)) == 0)
                    {
                        sb.append("0");
                    }
                    else
                    {
                        sb.append("1");
                    }
                }
            }
            sb.append("\n");
        }
        return sb.toString();
    }


}