Java convert Byte Array of ASCII values to int - java

After reading a ByteBuffer into b_array I am trying to convert the ascii values to int.
Output I am expecting is 129 after executing the code as (b_array[] has the decimal equivalents of ascii codes 49,50,59)
Can some one please tell me where am I doing wrong here. I am doing a 0xFF to make it a unsigned value in java and then OR operation to move the bytes.
byte[] b_array=new byte[3];
buffer.get(b_array,0,3);
// Contents inside the b_array in ascii code
// b_array[0]=49;
// b_array[1]=50;
// b_array[2]=57;
int value= b_array[2] & 0xFF | (b_array[1] & 0xFF) << 8 | (b_array[0] & 0xFF) << 16;
System.out.println(value);

Your current approach is effectively treating the three values as a 24-bit number - effectively 0x313239.
It sounds like you should be converting it into a string, then parsing that:
String text = new String(b_array, StandardCharsets.US_ASCII); // "129"
int value = Integer.parseInt(text);

Related

Getting individual bytes from hexadecimal value

Is there is a way I can get individual Bytes from a hexa decimal value in java
If I have a hexadecimal value 0x190(400), I want to get 0x90 and 0x01
If I have a hexadecimal value 0x89(137), I want to get 0x89 and 0x00
I am new to these and unable to find a way to get them individually.
Thank you for your help in advance
Thanks
R
If your number is represented as the integral value, you can use bit mask to isolate particular byte.
int value = 0x190;
byte byteValue = (byte) ((value >>> i*8) & 0xff);
String byteAsString = String.format("0x%02x", byteValue);
where i represents i-th byte (starting at 0)
If is string value
like this:
let hexDecimal = "0x89(137)";
let splitValue = hexDecimal .split("(");
let response = splitValue[0]; `

What does the statement "out |= ( in & 0x7F ) << ( bytes++ * 7 );" mean in java?

I was looking around the Minecraft's internal packet handling when I saw their VarInt reading code to read the packet length. As a java developer that does not have any course of java I was confused when I saw the statement out |= ( in & 0x7F ) << ( bytes++ * 7 );. Can someone please explain it to me? Thanks in advance!
If you want the whole code, just check the readVarInt function on BungeeCord's Github https://github.com/SpigotMC/BungeeCord/blob/master/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java#L70 .
I didn't look at the link you included, but I would expect this line to be called in a loop to convert a number stored as a collection of 7-bit values back to an int or long.
The line you gave can be expanded to this:
int value = in & 0x7F; // Grab 7 bits of data from "in"
int shift = bytes * 7; // Calculate shift amount based on byte index
bytes = bytes+1; // Increment byte index (from bytes++)
out = out | (value << shift); // Shift value and OR into output integer/long

How to get integer value from byte array returned by MetaMessage.getData()?

I need to get the tempo value from midi file. I found out, that the set_tempo command has value 0x51, so i have this piece of code:
for (int i = 0; i < tracks[0].size(); i++) {
MidiEvent event = tracks[0].get(i);
MidiMessage message = event.getMessage();
if (message instanceof MetaMessage) {
MetaMessage mm = (MetaMessage) message;
if(mm.getType()==SET_TEMPO){
// now what?
mm.getData();
}
}
}
But the method getData() returns an array of bytes! How can I convert it to normal human form, a.k.a. integer?
I have read it is stored in format like this: "tt tt tt", but the whole big/little endian, signed/unsigned, and variable length things make it too confusing.
Tempo is a 3-byte big-endian integer and Bits Per Minute is calculated asBPM = 60,000,000 / (tt tt tt)
byte[] data = mm.getData();
int tempo = (data[0] & 0xff) << 16 | (data[1] & 0xff) << 8 | (data[2] & 0xff);
int bpm = 60000000 / tempo;
I use:
mpq = ((data[0] & 0x7f) << 14) | ((data[1] & 0x7f) << 7) | (data[2] & 0x7f);
Where mpq represents microseconds per quarter note or microseconds per beat.
The reasoning for this is that Midi messages only use 7 bits in each byte to represent data. It should also be noted that, in Java, a byte data type (of which data is an array) is a signed integer and only has room for 7 data bits.
Since making this post I have had the following response from the MIDI Association:
The parameter number (tttttt) is a 24 bit unsigned integer, in big endian format.
"Set tempo" is a meta-event, belonging to the SMF specification. It applies only to Standard MIDI Files, and like the other meta-events are not supposed to be transmitted over the wires on real time. On the other hand, the Data Byte description that is confusing you applies to the over-the-wire protocol.
The original answer to this topic is therefore correct.

How to convert binary string to the byte array of 2 bytes in java

I have binary string String A = "1000000110101110". I want to convert this string into byte array of length 2 in java
I have taken the help of this link
I have tried to convert it into byte by various ways
I have converted that string into decimal first and then apply the code to store into the byte array
int aInt = Integer.parseInt(A, 2);
byte[] xByte = new byte[2];
xByte[0] = (byte) ((aInt >> 8) & 0XFF);
xByte[1] = (byte) (aInt & 0XFF);
System.arraycopy(xByte, 0, record, 0,
xByte.length);
But the values get store into the byte array are negative
xByte[0] :-127
xByte[1] :-82
Which are wrong values.
2.I have also tried using
byte[] xByte = ByteBuffer.allocate(2).order(ByteOrder.BIG_ENDIAN).putInt(aInt).array();
But it throws the exception at the above line like
java.nio.Buffer.nextPutIndex(Buffer.java:519) at
java.nio.HeapByteBuffer.putInt(HeapByteBuffer.java:366) at
org.com.app.convert.generateTemplate(convert.java:266)
What should i do now to convert the binary string to byte array of 2 bytes?Is there any inbuilt function in java to get the byte array
The answer you are getting
xByte[0] :-127
xByte[1] :-82
is right.
This is called 2's compliment Represantation.
1st bit is used as signed bit.
0 for +ve
1 for -ve
if 1st bit is 0 than it calculates as regular.
but if 1st bit is 1 than it deduct the values of 7 bit from 128 and what ever the answer is presented in -ve form.
In your case
1st value is10000001
so 1(1st bit) for -ve and 128 - 1(last seven bits) = 127
so value is -127
For more detail read 2's complement representation.
Use putShort for putting a two byte value. int has four bytes.
// big endian is the default order
byte[] xByte = ByteBuffer.allocate(2).putShort((short)aInt).array();
By the way, your first attempt is perfect. You can’t change the negative sign of the bytes as the most significant bit of these bytes is set. That’s always interpreted as negative value.
10000001₂ == -127
10101110₂ == -82
try this
String s = "1000000110101110";
int i = Integer.parseInt(s, 2);
byte[] a = {(byte) ( i >> 8), (byte) i};
System.out.println(Arrays.toString(a));
System.out.print(Integer.toBinaryString(0xFF & a[0]) + " " + Integer.toBinaryString(0xFF & a[1]));
output
[-127, -82]
10000001 10101110
that is -127 == 0xb10000001 and -82 == 0xb10101110
Bytes are signed 8 bit integers. As such your result is completely correct.
That is: 01111111 is 127, but 10000000 is -128. If you want to get numbers in 0-255 range you need to use a bigger variable type like short.
You can print byte as unsigned like this:
public static String toString(byte b) {
return String.valueOf(((short)b) & 0xFF);
}

Java - strange errors with unsigned values

There is 2-bytes array:
private byte[] mData;
and method:
public void setWord(final short pData) {
mData[0] = (byte) (pData >>> 8);
mData[1] = (byte) (pData);
}
I wrote the simple test:
public void testWord() {
Word word = new Word();
word.setWord((short) 0x3FFF);
Assert.assertEquals(0x3F, word.getByte(0));
Assert.assertEquals(0xFF, word.getByte(1));
}
The second assert fails with message "Expected 255, but was -1".
I know, that 0xFF signed short is, in fact, -1, but why JUnit thinks, that they are not equal? And, what is the correct way to implement such classes?
Java does not support unsigned types, so in order for a value to be 255, it must not be a signed byte, which is incapable of holding the value of 255. The 0xFF constant value will be taken as a signed int, and for the comparison, the byte value 0xFF will be converted to an int at -1 as well.
You need to type cast the literal 0xFF to be a byte. Change the assert to be Assert.assertEquals((byte)0xFF, word.getByte(1)); Then the left hand side will evaluate to -1 as well as the right.
The comment from biziclop is correct.
Any Integer number you specify in your code is considered an Integer unless marked otherwise.
Change your assertion to:
Assert.assertEquals((byte)0xFF, word.getByte(1))
And it should pass fine - as the first two bytes of the integer will be considered as a
byte.
Bitwize speeking - basically when you write 0xFF the compiler interprets it as 0x000000FF which is 255.
You want 0xFFFFFFFF which is -1.
Casting to byte is the correct solution here
There are no unsigned types in java.
0xFF is the int 255 and casted to byte overflows to -1.
I usually work with bytes as integers if I want them unsigned. I usually do that this way:
int b1 = getByte() & 0xFF;
For example:
byte byte1 = 0xFF; // 255 = -1
byte byte2 = 0xFE; // 254 = -2
int int1 = (byte1 & 0xFF) + (byte1 & 0xFF); // 255 + 254 = 509

Categories

Resources