alright, so my code to read bytes into a int is like so:
int offset = (byte << 16) | (byte2 << 8) | byte3;
And it's reading the bytes "00 00 be" as -66.
How do I read it as the 190 it's meant to be?
byte b = -66;
int i = b & 0xff;
byte b = -66;
int i = b < 0 ? b + 256 : b;
It might be useful declare helper function for this.
Related
I know there are many similar questions in here, but I have some weird case. What I want to do is to convert a byte[4] to an int.
Here is the conversion from int to byte:
int data24bit = 51;
for (int i = 0; i < 3; i++) {
data8bit = (byte)(data24bit & 0x0000FF);
data24bit = data24bit >> 8;
byte_file.put(data8bit);
}
So far is clear enough. After that I want to read this 4 bytes to get the 51 back. I tried to do it by different ways:
Reading 4 bytes:
byte[] bytes = new byte[4];
for (int i = 0; i < 3; i++) {
byte b = dis.readByte();
bytes[i] = b;
}
// bytes[3] = (byte)(0x000000);
Convert bytes to int:
int value = 0;
value = ((0xFF & bytes[0]) << 24) | ((0xFF & bytes[1]) << 16) |
((0xFF & bytes[2]) << 8) | (0xFF & bytes[3]);
or
value = ByteBuffer.wrap(bytes).getInt();
or
value = new BigInteger(bytes).intValue();
I always get 855638016 as result where 51 is expected.
When I debug the code and look into the byte array I can see the following content: [51, 0, 0, 0].
What am I doing wrong?
The problem is that you're writing the bytes in little-endian (least significant byte first), but read it back assuming big-endian.
After writing it out, your byte array looks like this:
[51, 0, 0, 0]
Then you're trying to convert that back into an integer, like in this example from your post:
value = ((0xFF & bytes[0]) << 24)
| ((0xFF & bytes[1]) << 16)
| ((0xFF & bytes[2]) << 8)
| (0xFF & bytes[3]);
If you fill in the actual values, that calculation is basically this:
value = 51 * 256 * 256 * 256
+ 0 * 256 * 256
+ 0 * 256
+ 0
= 855638016
While what you actually want is this:
value = 0 * 256 * 256 * 256
+ 0 * 256 * 256
+ 0 * 256
+ 51
= 51
The fixed calculation would thus be this:
value = ((0xFF & bytes[3]) << 24)
| ((0xFF & bytes[2]) << 16)
| ((0xFF & bytes[1]) << 8)
| (0xFF & bytes[0]);
Ok stupid enough but I just didn't preserve the byte order.
[51, 0, 0, 0] -> is 855638016
[0, 0, 0, 51] -> is 51
i have binary file with unsigned shorts. I need to take unsigned value from this bytes to primitive short in JAVA. Byte order is Little Endian. I trying in this way:
byte[] bytes = new byte[frameLength];
for(int i = 0; i < fh.nFrames; i++) {
raf.readFully(bytes);
for(int j = 2; j < frameLength/2; j++) {
short s;
s = (short) (bytes[2*j + 1] << 8 | bytes[2 * j]);
System.out.println(s);
System.out.println(Integer.toBinaryString(s));
}
}
Example:
case 1(ok):
unsigned short : 8237
in hex(little endian): 2D 20
in binary(big endian): 0010 0000 0010 1101
and System.out.println(Integer.toBinaryString(s)) give us
10000000101101. It's correct.
case 2(not ok)
unsigned short: 384
in hex(little endian): 80 01
in binary(big endian): 0000 0001 1000 0000
and System.out.println(Integer.toBinaryString(s)) give us
11111111111111111111111110000000.
System.out.println(s) give us -128. It's not correct.
How i can get 384 value from this?
Someone has idea why it doesn't working?
Java converts everything to int before doing integer computations, and as bytes are signed, you get a sign extension. You must force bytes to stay in [0; 255] range by bitwise and-ing them with 0xFF:
s = (short) ((bytes[2*j + 1] & 0xFF) << 8 | (bytes[2 * j] & 0xFF));
What is the difference between:
int n = (b1 & 0xff) << 24 | (b2 & 0xff) << 16 | (b3 & 0xff) << 8 | b4 & 0xff
and
int n = b1 << 24 | b2 << 16 | b3 << 8 | b4
? Why should we AND each byte with 255?
First you need to understand that b1 <<< 24 expects the a operand to be of type int or long. So, if b1 is a byte, Java will convert it to an int before the shift takes place.
That conversion happens by mapping each byte value into the corresponding int value. The problem is that byte is a signed type, which means that the possible values are -128 through to +127. Therefore, when you convert a byte with a negative value, you will get an int with a negative value; e.g. the byte 11111111 (binary) which is -1 becomes 11111111111111111111111111111111 (binary) which is also -1.
Those leading ones are the result of sign extension, and we do NOT want them if we are about to shift them and combine them in a bitwise fashion.
Hence, you will often see a byte being masked with 0xff to remove the (unwanted) results of sign extension after the conversion. For example
11111111111111111111111111101110 &
00000000000000000000000011111111
gives
00000000000000000000000011101110
Let me assume types of b1, b2, b3 and b4 are byte.
In this case, their values will be sign extended and if they are negative, the result will be wrong if AND isn't used.
Demo:
class Test {
public static void main(String[] args) {
byte a = (byte)128;
int x1 = a << 8;
int x2 = (a & 0xff) << 8;
System.out.println(x1);
System.out.println(x2);
}
}
Output:
-32768
32768
I've got a long variable and I need to reverse its byte order. For example: B1, B2, ... , B8 I should return a long that consists of B8, B7, ..., B1. How can I do it by using bitwise operations?
you can use Long.reverseBytes(long)
Or for more methods which include bitwise operations, you can refer to this stack overflow question
Heres another method you may like, I'd still recommend the above but it's better than bitwise where you can easily make mistakes.
Bytebuffer
byte[] bytes = ByteBuffer.allocate(8).putLong(someLong).array();
for (int left = 0, right = bytes.length - 1; left < right; ++left, --right) {
byte temp = bytes[left];
bytes[left] = bytes[right];
bytes[right] = temp;
}
I am trying to steer you away from bitwise solutions because they are cumbersome and very easy to mess up if you do not know what you are doing... But bitwise would look like this:
byte[] bytes = new byte[8];
// set the byte array from smallest to largest byte
for(int i = 0; i < 8; ++i) {
byte[i] = (your_long >> i*8) & 0xFF;
}
// build the new long from largest to smallest byte (reversed)
long l = ((buf[0] & 0xFFL) << 56) |
((buf[1] & 0xFFL) << 48) |
((buf[2] & 0xFFL) << 40) |
((buf[3] & 0xFFL) << 32) |
((buf[4] & 0xFFL) << 24) |
((buf[5] & 0xFFL) << 16) |
((buf[6] & 0xFFL) << 8) |
((buf[7] & 0xFFL) << 0) ;
You might want to use Long.reverseBytes instead of using bitwise operations. See the Java Reference for details.
Otherwise, you could have a look at the JDK sources (src.zip in your JDK folder) in Long.java but mind the copyright by Oracle.
Here's an old trick that you can use to endian swap a register:
static long swapblock(long a, long mask, int shift) {
long b1 = a & mask; // extract block
long b2 = a ^ b1; // extract remaining bits
return (b1 << shift) |
((b2 >> shift) & mask); // mask again to clear sign extension
}
static long endianswap(long a) {
a = swapblock(a, 0x00000000ffffffffL, 32);
a = swapblock(a, 0x0000ffff0000ffffL, 16);
a = swapblock(a, 0x00ff00ff00ff00ffL, 8);
return a;
}
The idea is to progressively swap sub blocks until you reach the desired level you want to stop at. By adding swaps of sizes 4, 2, and 1, you can change this into a bit mirror function.
There is only one tricky bit due to lack of unsigned types in java. You need to mask out high order bits when shifting right, because the sign bit is replicated by the shift amount, filling the high order bits with ones (0x8000000000000000 >> 8 is 0xFF80000000000000).
long reverse(long x){
x = (x >> 32) | (x << 32); // step 1
x = ((x & 0xffff0000ffff0000 ) >> 16)
| ((x & 0x0000ffff0000ffff ) << 16); // step 2
x = ((x & 0xff00ff00ff00ff00 ) >> 8)
| ((x & 0x00ff00ff00ff00ff ) << 8); // step 3
return x;
}
If we assume that bitwise operator works in O(1) time, reverse function works in O(lg(number of bits) ) time.
Explanation
Step 0 : B1 B2 B3 B4 B5 B6 B7 B8
Step 1 : B5 B6 B7 B8 B1 B2 B3 B4
Step 2 : B7 B8 B5 B6 B3 B4 B1 B2
Step 3 : B8 B7 B6 B5 B4 B3 B2 B1
Plain answer with loops:
public static long byteReverse(long a) {
long result = 0;
for(int i = 0; i < 8; i++){
// grab the byte in the ith place
long x = (a >> (i*8)) & (0b11111111);
result <<= 8;
result |= x;
}
return result;
}
bitwise only:
public static long byteReverse(long a) {
a = (a << 32) | (a >>> 32);
a = ((a & 0xffff0000ffff0000L) >>> 16) | ((a & 0x0000ffff0000ffffL) << 16);
a = ((a & 0x00ff00ff00ff00ffL) << 8) | ((a & 0xff00ff00ff00ff00L) >>> 8);
return a;
}
I'm trying to flip some bytes around in Java and the function I have is working correctly for some bytes and failing for others.
The function I am using is this:
public static int foldInByte(int m, int pos, byte b) {
int tempInt = (b << (pos * 8));
tempInt = tempInt & (0x000000ff << (pos * 8));
m = m | tempInt;
return m;
}
And the code that implements this is:
byte[] bitMaskArray = new byte[]{
byteBuffer.get(inputIndex),
byteBuffer.get(inputIndex + 1),
byteBuffer.get(inputIndex + 2),
byteBuffer.get(inputIndex + 3)};
int tempInt = 0;
tempInt = foldInByte(0, 3, bitMaskArray[3]);
tempInt = foldInByte(tempInt, 2, bitMaskArray[2]);
tempInt = foldInByte(tempInt, 1, bitMaskArray[1]);
tempInt = foldInByte(tempInt, 0, bitMaskArray[0]);
bitMask = tempInt;
The bytes are being read from a ByteBuffer with the byteOrder being Little Endian.
For example, the bytes 00 01 B6 02 set the bitMask to: 2B60100 - which works perfectly in my program.
However, if the bytes are A0 01 30 00, the bitMask is set to: 3001A0 - which has stipped the last zero from the bitmask.
Is there any way I can stop Java from stipping off trailing zeros?
I hope that makes sense.
Thanks
Tony
The zeros are not being stripped -- both examples cited are correct.
00 01 B6 02 is the 4-byte little-endian for 2B60100
A0 01 30 00 is the 4-byte little-endian for 3001A0
The zeros are there, but probably just not being printed. The System.out.print family of calls will not print leading zero digits.
I might mention that your method is needlessly complex. Here is a single method that computes the same value:
static int extractLittleEndian4(byte[] buf, int index)
{
int a = buf[index+0]&0xff, b = buf[index+1]&0xff, c = buf[index+2]&0xff, d = buf[index+3]&0xff;
return a | (b << 8) | (c << 16) | (d << 24);
}
It looks like you have a ByteBuffer filled with your bytes already. Why don't you let the ByteBuffer reverse the bytes for you? Just add the bytes to the buffer (BIG_ENDIAN is the default if you want to add an integer instead of bytes) and then change the order before reading the integer.
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
int output = byteBuffer.getInt(0);
If all you're doing is reversing the byte order, let the library do the work for you. If you happened to start with an integer value, you can even just do this:
int input = ...;
int output = Integer.reverseBytes(input);