makingitwork
makingitwork

Reputation: 149

turn my 32 character int into a 32 byte array as is in Java

I am wondering how can I turn my 32 character int into a 32-byte array as it is represented.

Example:

I have this int:

int test = 123456789;

And I want to turn it into this:

byte[] Write_Page_Four = new byte[] {  

                                (byte) 0x00, (byte) 0x00,
                                (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                                (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                                (byte) 0x00, (byte) 0x01, (byte) 0x23, (byte) 0x45,
                                (byte) 0x67, (byte) 0x89};

Currently, I'm thinking of splitting my int by 2 and just manually assigning them to the byte array but I am having some troubles in doing so, and I believe that this is not the best practice for my problem.

This is what I have ATM, which is returning error and still work on progress though and I could use some advice on it:

String test2 = "01";
String test1 = "0x"+test2; 
byte test =  Byte.valueOf(test1);
System.out.println("teeeeest-----"+test);

byte[] Write_Page_Four = new byte[] {(byte) test};

And this one is returning an error:

java.lang.NumberFormatException: For input string: "0x01"

Upvotes: 1

Views: 3169

Answers (3)

user4668606
user4668606

Reputation:

Instead of processing the textual representation of the number I'd recommend to simply calculate the single numbers:

Get two digits of the number each time:

int inp = 1234...;

for(int lowerBound = 1 ; lowerBound < Integer.MAX_VALUE ; lowerBound *= 100)
    //twoDigit contains two digits of the input-number
    int twoDigit = (inp /lowerBound) % 100;

Transform these two digits into a byte:

byte transform(int i){
    if(i == 0)
        return 0x00;

    int lsd = (i % 10); //least significant digit of the input (decimal)
    int msd = (i / 10); //most significant digit

    //merge lsd and msd into a single number, where the lower 4 bits are reserved for
    //lsd and the higher 4 bits for msd
    return lsd | (msd << 4);
}

The complete code would look like this:

import java.util.Arrays;

public class test
{
    private static final int BYTES = 4;

    public static void main(String[] args){
        int v = 12345678;

        int at_arr = BYTES - 1;
        byte[] result = new byte[BYTES];//int is 32-bit/4 byte long

        for(int lowerBound = 1 ; lowerBound < Integer.MAX_VALUE && at_arr > -1; lowerBound *= 100, at_arr--)
            result[at_arr] = transformDigits((v / lowerBound) % 100);

        for(byte b : result)
            System.out.print(" 0x" + Integer.toString(b , 16) + ",");
        System.out.println();
    }

    static byte transformDigits(int i){
        if(i == 0)
            return 0x00;

        int lsd = (i % 10); //least significant digit of the input (decimal)
        int msd = (i / 10); //most significant digit

        //merge lsd and msd into a single number, where the lower 4 bits are reserved for
        //lsd and the higher 4 bits for msd
        return (byte) (lsd | (msd << 4));
    }
}

This code can be used basically for any integral type, if the types and value of BYTES are updated appropriately.

Upvotes: 2

Andreas
Andreas

Reputation: 159096

Here's how to convert an int to a byte[]:

int test = 123456789;

byte[] bytes = new byte[4];
bytes[0] = (byte)(test >> 24);
bytes[1] = (byte)(test >> 16);
bytes[2] = (byte)(test >> 8);
bytes[3] = (byte)test;

System.out.printf("%02x %02x %02x %02x%n", bytes[0], bytes[1], bytes[2], bytes[3]);

Output

07 5b cd 15

You can also inline it, if you want:

int test = 123456789;
byte[] bytes = new byte[] { (byte)(test >> 24),
                            (byte)(test >> 16),
                            (byte)(test >> 8),
                            (byte)test };
System.out.printf("%02x %02x %02x %02x%n", bytes[0], bytes[1], bytes[2], bytes[3]);

Upvotes: 2

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476659

What is causing problems

Byte.valueOf doesn't parse data like the Java compiler does: it expects as input as a decimal number.

What you can use however, is Byte.valueOf(String,int) with an arbitrary radix. In that case you can solve it using:

byte test =  Byte.valueOf(test2,16); //using test2, not test1

Mind that should not add "0x" in the front. Nevertheless this is an inefficient way to do this.

Ints are 32-bits, not 32-bytes

A second problem is that you state that you can store a number like 12345678901234567890123456789011 into an int. You cannot. An int has 32 bits. This means its representation is limited to more or less 2.1B. So I think you mean you store 12345678901234567890123456789011 in a String?

Number systems

Mind that the number 12345678901234567890123456789011 is not represented internally as (byte) 0x12, (byte) 0x34,... unless you are working with binary coded decimals. This is because a computer uses the binary number system (and thus groups bytes with the hexadecimal representation), whereas humans use the decimal representation. 123456789 for instance will be represented as 0x07,0x5B,0xCD 0x15.

Serializing an int (or other datastructure) using an array of bytes

You can convert an int (and other datatypes) into an array of bytes using this code:

ByteBuffer b = ByteBuffer.allocate(4);
b.putInt(test);
byte[] result = b.array(); //result will be 4 bytes,
//since you can represent any int with four bytes.

Or, in case you want to represent the int like the way you do this, you could use the following method:

int t = test;
byte[] dat = new byte[5];//at most 5 bytes needed
for(int j = 4; test != 0; j--) {
    int rm = t%100;
    dat[j] = (byte) (rm%10+((rm/10)<<8));
    t /= 100;
}
//result is dat

Upvotes: 3

Related Questions