Hey I need to store the following hex value in a byte array - 0xCAFEBABEDEADBEEF.
So I tried to store it like so.
byte[] v0 = {11001010,11111110,10111010,10111110,11011110,10101101,10111110,11101111};
where 11001010 is CA in binary, 11111110 is FE in binary etc.
But I get an error saying 11001010 is an int, so I presume this is because bytes are signed bytes in java, and we can only have values between +127 and -128.
So is there way I can do this in java(maybe using unsigned bytes...if they exist!?)
Thanks guys.
Put 0b in front of the number. You may also have to cast to byte:
byte[] v0 = {(byte)0b11001010,(byte)0b11111110,...};
The 0b prefix means it is a binary number.
If you want it to be easier to read, you can use 0x for hexadecimal:
byte[] v0 = {(byte)0xCA,(byte)0xFE,(byte)0xBA,(byte)0xBE,...};
Here's a way to do it (binary form) if you're using a Java version less than 7:
byte[] v0 = {Byte.parseByte("11001010", 2),...);
The literal 11001010 represents a decimal of int type and of value 11,001,010 - that is 11 milions and something.
If you're using Java 7, you can define binary literals using the 0b prefix, such as 0b11001010. To improve readability, you can put underscores in the values, such as 0b_1100_1010.
However, note that the type of even such binary (or hexadecimal) literal is still int. This, together with the fact that bytes are (unfortunately) signed in Java (thus their value is in range -128 to 127) results in the problem that a literal with a value larger than 127 has to be manually cast to byte:
// 0b_1001_0001 or 0x91 is 145 in decimal
byte b1 = (byte) 0b_1001_0001;
byte b2 = (byte) 0x91;
However, the value of such byte will be -111 (145 - 256). To get back the unsigned value, you need to manually add the module (256) to the value:
int i1 = b1 + 256;
int i2 = b1 & 0xff;
// both i1 and i2 are 145
For more information see this question
If write byte to byte, you can use:
byte[] v0 = {0b11001010, 0b11111110, 0b10111010, ... }
or
byte[] v0 = {0xCA, 0xFE, ... }
Related
I have a problem. I receive a double val=80.22. Then I split it:
String[] arr=String.valueOf(val).split("\\.");
int[] intArr=new int[2];
intArr[0]=Integer.parseInt(arr[0]); // 80
intArr[1]=Integer.parseInt(arr[1]); // 22
Now i need to put this values into a byte[]. But I don't need the value into the byte[], I need it like this: 0x80 , 0x22.
What I have tried:
byte firstbyte = Byte.parseByte(arr[0], 16);
byte secondbyte = Byte.parseByte(arr[1], 16);
This works fine but only to the value 80, then I receive:
java.lang.NumberFormatException: Value out of range. Value:"80" Radix:16
But I don't get it. I need the number up to the value 100.
I have tried to write it into a string like string = 0x80 but I don't know how to put it into the byte[] then.
Thanks for your help!
Its hard for me to understand the question, but if you want to put a number up to the value 100 in a byte data type you just need to write:
byte firstbyte = (byte)intArr[0];
byte secondbyte = (byte)intArr[1];
Because 0x80 is an hexadecimal value and its worth to the decimal 128 which is too big for that data type.
Bytes are signed in Java. The highest value in a byte, in hexadecimal is 7F, so 80 is too big. Unfortunately there is no parseUnsignedByte.
The workaround is to use the type with the next higher range up, a short, then cast the result back to byte.
byte firstbyte = (byte) Short.parseShort(arr[0], 16);
byte secondbyte = (byte) Short.parseShort(arr[1], 16);
This will turn "80" into -128, but the byte representation is correct: 1000 0000, or 80 in hexadecimal.
Note that if the short value is out of the range of even an unsigned byte (at least 256, or "100" in hexadecimal), then this will silently truncate the value to the least significant 8 bits, i.e. 256 -> 0, 257 -> 1, etc.
byte max value is 2^7 - 1 = 127 in dec.
0x80 is hex representation of 128 in dec.
Hex counts from 0 to 9 then from A to F.
So, 80 in dec will be 0x50.
Simply avoid second parameter in Byte.parseByte() or use Byte.valueOf("80")
What I want to do is take a decimal integer, convert it into hexadecimal, and then separate the bytes.
It's my understanding that ByteBuffer is the best way to do this. The integer will not exceed 65535, so the hex number is guaranteed to be 2 bytes. For an example, I have an integer of 40000 (hex value 9C40).
int n1 = 40000;
ByteBuffer b = ByteBuffer.allocate(2);
b.putInt(n1);
However, I get the following error when I run the program:
Exception in thread "main" java.nio.BufferOverflowException
What am I doing wrong? Shouldn't 9C40 be written into b (with b[0] = 9C and b[1] = 40)?
Also, once I get past this, if I want to convert the value stored in b[0] (which is 9C) to decimal (which is 156), would I just use the following code?
int n2 = b.get(0);
As you are working with a ByteBuffer, it stores an amount of x allocated bytes. Now you allocated 2 bytes and you try to store a datatype that has the size of 4 bytes. So the buffer will run out of bounds as the message said. If you want to store this data in a two byte sized buffer, you either use a short (16 bit - 2 bytes) or you allocate 4 bytes for your ByteBuffer.
With short:
ByteBuffer bb = ByteBuffer.allocate(2);
short myShort = (short) 40000;
bb.putShort(myShort);
System.out.println(String.format("%02X, %02X", bb.get(0), bb.get(1)));
With int:
ByteBuffer bb = ByteBuffer.allocate(4);
int myInt = 40000;
bb.putInt(myInt);
System.out.println(String.format("%02X, %02X", bb.get(2), bb.get(3)));
Output: 9C, 40
The data type you used to store the number 40000 is int, which requires 4 bytes of space. Yes I know the number won't exceed 65535 but the computer doesn't. You have to change it to an appropriate data type that can be stored in 2 bytes.
That data type, is short.
But there's another problem if you used short, you can't really store 40000 in short in Java is signed, so its max value is 32767.
So to store your 40000, you have to store -25536 instead in a short, because of overflow.
short n1 = (short)40000; // this will cause n1 to store -25536
ByteBuffer b = ByteBuffer.allocate(2);
b.putShort(n1);
Now it's time to print out the bytes. Bytes in Java are signed as well. So if you print this:
System.out.println(b.get(0));
System.out.println(b.get(1));
You'd get
-100
64
64 is expected since 64 in hex is 40, but why -100? Since bytes are signed, 156 can't be represented as 156. 156 in a signed byte is -100.
Instead of ByteBuffer I prefer Integer class which can convert the integer value to hex string & you can get each byte by index of method.
Use following code it do that
int n = 4000;
String hex = Integer.toHexString(n);
In this way you can get the hex value of any integer for one one byte use indexOf() method of string clas
You can get return the hex value as integer using valueOf() method in Integer class which takes two arguments one is string and another is radix
We have a file which contains byte array in particular format like header and then followed by data. This file is generated by another java program and then we are reading that same file through another java program in the same format in which it was written.
The program which is making that file, populates lengthOfKey as byte which is right as that's what we need as shown below.
for (Map.Entry<byte[], byte[]> entry : holder.entrySet()) {
byte typeKey = 0;
// getting the key length as byte (that's what we need to do)
byte lengthOfKey = (byte) entry.getKey().length;
byte[] actualKey = entry.getKey();
}
Now as byte can only store maximum value as 127, we are seeing for some of our record lengthOfKey is coming as negative while we read the file as shown below:
Program which is reading the file:
byte keyType = dis.readByte();
// for some record this is coming as negative. For example -74
byte lengthOfKey = dis.readByte();
Now my question is : Is there any way I can find out what was the actual length of key because of that it got converted to -74 while writing it. I mean it should be greater than 127 and that's why it got converted to -74 but what was the actual value?
I think question would be how to convert negative byte value to either short or integer? I just wanted to verify to see what was the actual length of key because of that it got converted to negative value.
If the original length from entry.getKey().length is greater than 255, then the actual length information is lost. However, if the original length was between 128 and 255, then it can be retrieved.
The narrowing conversion of casting to byte keeps only the least significant 8 bits, but the 8th bit is now interpreted as -128 instead of 128.
You can perform a bit-and operation with 0xFF, which will retain all bits, but that implicitly widens the value back to an int.
int length = lengthOfKey & 0xFF;
lengthOfKey (byte = -74): 10110110
Widening it to an int, with sign extension:
lengthOfKey (int = -74): 11111111 11111111 11111111 10110110
Masking out the last 8 bits as an int:
length (int = 182): 00000000 00000000 00000000 10110110
That will convert a negative byte back to a number between 128 and 255.
If you use Guava, it provides a number of unsigned math utilities, including UnsignedBytes.
UnsignedBytes.toInt(lengthOfKey);
Notice their implementation of toInt() is exactly what #rgettman suggests.
To convert an assumed unsigned byte to an int.
int value = (byteValue >= (byte) 0) ? (int) byteValue : 256 + (int) byteValue;
I receive datas, from a RS422 communication, in a byte tab (byte[]).
Some of my data are in two's complement binary with the following rules :
Significant bits Two's complement
MSB LSB
00000000 0
00000001 + LSB
01111111 + MSB - LSB
10000000 - MSB
10000001 - MSB + LSB
11111111 - LSB
To convert byte[] data to decimal, in pure binary, I use the following code :
Byte b05 = new Byte(new Integer(0x7A).byteValue()); // I use those bytes for my test
Byte b06 = new Byte(new Integer(0x00).byteValue());
Byte[] byteTabDay = new Byte[2] ;
byteTabDay[0] = b05 ;
byteTabDay[1] = b06 ;
int valueDay = byteTabDay[1] << 8 | byteTabDay[0] ;
System.out.println("day :" + valueDay); // print 122
But I don't know how to convert, like previously, byte[] that contain two's complement binary data like that:
Byte b20 = new Byte(new Integer(0x00).byteValue());
Byte b21 = new Byte(new Integer(0xFF).byteValue());
Byte b22 = new Byte(new Integer(0x3C).byteValue());
Those data contain, in theory, the value (more or less) : 1176
So I need help cause I don't understand how I can convert my byte data which contains two's complement binary to decimal.
Two's complement binary is the standard for representing numbers with negative numbers included.
For three-bit numbers:
Base 2 (One's Two's
complement) complement
000 = 0
001 = 1
010 = 2
011 = 3
100 = 4 -3 -4
101 = 5 -2 -3
110 = 6 -1 -2
111 = 7 -0 -1
Java assumes two's complement: the most significant bit being 1 means negative..
Also in java byte, short, int, long are signed.
As an aside, you used the Object wrappers for the primitive types. Primitive types are more immediate.
byte b05 = (byte) 0x7A;
byte b06 = (byte) 0x00; // MSB, positive as < 0x80
nyte[] byteTabDay = new byte[2];
byteTabDay[0] = b05;
byteTabDay[1] = b06;
int valueDay = ((int) byteTabDay[1]) << 8) | (0xFF & byteTabDay[0]);
System.out.println("day :" + valueDay); // print 122
What one has to do: keep the sign extension of the most significant byte, but for other bytes keep them to 8 bits by masking them with 0xFF.
The easiest way to convert an arbitrary byte array containing a two’s complement value to a decimal representation is new BigInteger(bytearray).toString().
This, however, expects the data to be in the big endian byte order. If the data is in little endian order as it seems in your question, you have to reverse it for the use with BigInteger.
byte[] bytearray={ 0x7A, 0x00 };
ByteBuffer b=ByteBuffer.allocate(bytearray.length);
for(int ix=bytearray.length; ix>0; ) b.put(bytearray[--ix]);
System.out.println(new BigInteger(b.array()).toString()); // print 122
If the length of the array matches a standard primitive value type size, you can use ByteBuffer to get the value directly:
byte[] bytearray={ 0x7A, 0x00 };
System.out.println(ByteBuffer.wrap(bytearray)
.order(ByteOrder.LITTLE_ENDIAN).getShort()); // print 122
However, don’t expect the value 1176.61254 as a result. That’s impossible.
If you think that this is the encoded value you will have to adapt your specification. There is no standard three-byte format for floating point values.
I need to convert decimal value like
int dec = 129;
into a byte value like
byte frame2 = (byte) 129;
but as you might already have guessed, it converts into an unexpected value. I want the byte value to be literally 129 instead of -127 (value of frame2).
How could you achieve it in Java? I would appreciate an explanation as well.
Thanks
You can't and most likely you don't need to. a byte is -128 to 127 by definition. However you can store any 256 different values in a byte if you want with encoding.
byte b = (byte) 129;
int i = b & 0xff; // == 129
or
byte b = (byte) (129 + Byte.MIN_VALUE);
int i = b - Byte.MIN_VALUE; // also 129.
I need to convert decimal value like
Stop right there. There is no such thing as a 'decimal value'. There are values, which are held in 2s-complement, and there are decimal representations.
int dec = 129;
That will be stored as 129(10), or 81(16).
into a byte value like
byte frame2 = (byte) 129;
The result of that will be -127, because bytes are signed in Java and your value sets the sign bit.
If you want to use the value as though it was 129, use (frame2 & 0xff). However it is quite likely that you don't need to do that at all.
Your question is actually about sign-extension of bytes in Java: it has nothing to do with decimals at all.