1

I have the following two-dimensional int array:

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

This two-dimensional array contains only zeros and ones. I want to read each line and make a byte[] (byte array) out of its contents. For instance, let's say that the first line is: 0101111000111...101, consisting of 128 numbers. I want this line to be a byte[] of 128 bits (which means 16 bytes).

What's the most efficient way to transform each line into a byte array? Bear in mind that maintaining the size is important. Since each lines consists of 128 "bits" the byte array should have a size of 16 bytes (128/8).

One way I've thought on how to do this is to make each line into a BigInteger and then convert it into byte array but unfortunately I can't produce the proper results. I've also tried some of the other options available to StackOverflow to no avail. For instance this solution produces an output of 512 and I don't understand why.

For the above reason I don't consider this post a duplicate since the various asks and answers don't take in mind the size of the byte array and its correlation to the int array.

6
  • As for your example-solution: 512 = 128 * 4 and int is 4 bytes long. That solution simply gets all bytes from an int. You want another kind of transformation, so you'll have to use another approach. Commented Feb 11, 2016 at 17:21
  • Can you guarantee that your first array will always be a multiple of 8? Commented Feb 11, 2016 at 17:23
  • @Paul Makes sense now that you mention it. Commented Feb 11, 2016 at 17:28
  • @AndrewWilliamson Indeed an important question. Yes, I can guarantee it. The size will always be divisible by 8. Commented Feb 11, 2016 at 17:28
  • 1
    So the result should be a byte b[][] = new byte[128][16], right? (And not a byte b[] = new byte[128*16] ...) Commented Feb 11, 2016 at 17:29

3 Answers 3

2

Here's code for a 1D array. You just repeatedly do that for the outer array of a 2D array.

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();

This is the more common Most Significant Bit First.
Answer by @AndrewWilliamson shows an algorithm for Least Significant Bit First.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah yeah, I didn't even think about bit ordering.
2

Since you know that the array will always be a multiple of 8, then you can safely convert from binary to bytes with bit manipulations.

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;
}

Alternatively, as @Andreas pointed out, Most Significant Bit normally comes first. Just change the for-loop to this:

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

Comments

1

The approach that you linked to converts the ints to bytes by simply considering the four individual bytes that an int consists of.

What you need is a method that sets individual bits in the resulting bytes. This can be done by checking whether each of the 128 values in the input array is 0 or 1, and setting the corresponding bit in the output array acoordingly. This can be done with each row independently.

Here is an MCVE that shows the conversion process and prints and compares the results:

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();
    }


}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.