سؤال

The goal is to convert every pair of bytes as a single unsigned 16bit int. In C I would define an array[500] of 16bit unsinged int pointer and would point it the the array of bytes, but in java I am not aware of such short cut. I know in Java there is no 16bit data type except char, however that is not an issue. We only need to copy every two consecutive two bytes into a single int of an array of integers. So the array of integer holds values of int ranging from 0 to 65535 (2^16-1).

هل كانت مفيدة؟

المحلول

I think that there are no nice tricks in Java like the aliasing you can do in C. You're going to have to do this by hand:

public int[] pack(byte[] bytes) {
    int n = bytes.length >> 1;
    int[] packed = new int[n];
    for (int i = 0; i < n; ++i) {
        int i2 = i << 1;
        int b1 = bytes[i2] & 0xff;
        int b2 = bytes[i2 + 1] & 0xff;
        packed[i] = (b1 << 8) | b2;
    }
    return packed;
}

(This can probably be sped up a bit, but probably not worth it for 1,000 elements unless it's being done a lot.) Note that the promotion from byte to int requires a bit of extra work to deal with unwanted sign extension.

نصائح أخرى

You could use ByteBuffer to spare the shifting and masking, which you often get wrong. (and there is signed vs. unsigned too)

ByteBuffer bb = ByteBuffer.wrap(bytes);
bb.order(ByteOrder.BIG_ENDIAN);  // or LITTLE_ENDIAN
short[] shorts = new short[bytes.length/2];
for (int i=0; i<shorts.length; i++)
   shorts[i] = bb.getShort();

Note - if you really want an "unsigned short", there is no such thing in java, so your array would have to be of integers. You would convert using

for (int i=0; i<intArray.length; i++) {
   short s = bb.getShort();
   intArray[i] = s & 0xFFFF; // mask off all the high order bits
}

There isn't really an unsigned 16-bit integer type in Java -- except maybe char, if you're feeling abusive of the language. That said, this is a wonderful time to use the popular Guava utility library:

public short[] pack(byte[] bytes) {
   short[] result = new short[bytes.length / 2];
   for (int i = 0; i < bytes.length; i += 2) {
     result[i/2] = Shorts.fromBytes(bytes[i], bytes[i+1]);
   }
}

And if you're really picky about performance, you could add a separate counter or use right shift instead of division, but that's straightforward enough.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top