将 int 数组转换为字节数组,同时保持大小
Convert an int array to a byte array while maintaining the size
我有以下二维 int
数组:
int[][] array = new int[128][128];
这个二维数组只包含 zeros 和 ones。我想读取每一行并从其内容中创建一个 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();
}
}
我有以下二维 int
数组:
int[][] array = new int[128][128];
这个二维数组只包含 zeros 和 ones。我想读取每一行并从其内容中创建一个 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();
}
}