r.m.ghimis
r.m.ghimis

Reputation: 43

Byte array to signed Integer

I have the fallowing piece of code that I try to understand what it does. I know that extracts an integer value from a byte value, but I don't really comprehend what it does and how it works:

public int decodeInt(byte[] input, int length) {
    int value = 0;
    int p = 0;
    int paddingPositions = 4 - length;
    for (int i = 0; i < 4; i++) {
        int shift = (4 - 1 - i) * 8;
        if (paddingPositions-- > 0) {
            value += (0 & 0x000000FF) << shift;
        } else {
            value += (input[p] & 0x000000FF) << shift;
            p++
        }
    }
    return value;
}

It seems to pad the value to get the high bits and low bits and sum them together somehow(the shift step looks very strange to me).

Upvotes: 0

Views: 111

Answers (1)

bvdb
bvdb

Reputation: 24730

I would call this function keepFirstXBytes(...). It seems to cut out the first part of a byte[] and return those bytes as an integer.

  • Like if your input is: { 0x01, 0x02, 0x03 }, and your length is 2, then it will output only the first 2 bytes. 0x0102.

There are some caveats.

  • The maximum value of length is 4. If you take a longer value, then it will just act as if it was 4. It will just take the first 4 bytes of the array. An integer can hold only 4 bytes after all.

How I would write it:

I'm wondering if it could be easier to read, if it used an arraycopy.

byte[] destination = new byte[length];
System.arraycopy(input, 0, destination, 0, length);

And then finally convert that to an integer. Which is kind of tricky for an array of variable length. So, I would borrow the function which I found here.

public static int pareAsBigEndianByteArray(byte[] bytes) {
    int factor = bytes.length - 1;
    int result = 0;
    for (int i = 0; i < bytes.length; i++) {
        if (i == 0) {
            result |= bytes[i] << (8 * factor--);
        } else {
            result |= bytes[i] << (8 * factor--);
        }
    }
    return result;
}

Seems like the code of the function given in your question does those 2 things in one go, which could be more efficient, but it looks really hard to read.

EDIT:

It's easier if you just always copy it to an array of length 4.

public static int decodeInt(byte[] input, int length) {
    length = java.lang.Math.min(4, length);
    byte[] destination = new byte[4];
    System.arraycopy(input, 0, destination, 4-length, length);
    int value = java.nio.ByteBuffer.wrap(destination).getInt();
    return value;
}

Upvotes: 1

Related Questions