Array of Bytes (as hex) conversion to Int issue. (Kotlin/Java) - java

I'm looking at parsing information from a temp/humidity sensor that was provided with the following instructions;
There are 6 bytes.
Temperature positive/negative: 0 means positive (+) and 1 means negative (-)
Integer part of temperature. Show in Hexadecimal.
Decimal part of temperature. Show in Hexadecimal.
Reserved byte. Ignore it.
Integer part of humidity. Show in Hexadecimal.
Decimal part of humidity. Show in Hexadecimal.
For example: 00 14 05 22 32 08 means +20.5C 50.8% & 01 08 09 00 14 05
means -8.9C 20.5%
as each byte is in hex & i need to covert this to an Int I followed this approach - Java code To convert byte to Hexadecimal but the values I get when validating their example don't make sense.In Kotlin I do;
val example = byteArrayOf(0, 14, 5, 22, 32, 8)
example.map { Integer.parseInt(String.format("%02X ", it),16)}
First Example output is;
0 = "00 "
1 = "08 "
2 = "09 "
3 = "00 "
4 = "0E "
5 = "05 "
Second Example output;
0 = "00 "
1 = "0E "
2 = "05 "
3 = "16 "
4 = "20 "
5 = "08 "
What am I doing wrong? I'm starting to think the manufactures instructions could be 'misleading'

A key thing you are missing here is that when passing in the it parameter to String#format, that value is a decimal int, not a hexadecimal int.
You instead want to map the value in the array directly to a string, then get its decimal value:
byte it = 14;
int x = Integer.parseInt(String.valueOf(it), 16);
System.out.println(x); // This will print 20
This should get you the expected result.
Note, your problem is slightly confusing because the numbers in your byte array are decimal numbers...already in their hex 'format'. There are a few ways this confusion can be fixed (assuming you have control of the array's type and/or contents):
Use String instead of byte
String it = "14";
int x = Integer.parseInt(it, 16);
System.out.println(x); // This will print 20
Store the values as hex and still convert (i.e., putting a 0x in front of each number)
byte it = 0x14;
int x = Integer.parseInt(String.format("%02X", it), 16);
System.out.println(x); // This will print 20
Store the values as hex and don't convert, because there is no need
byte it = 0x14;
System.out.println(it); // This will print 20
If you go with the second bullet, though convoluted, what you have right now should work, but the third option would be best if you are hardcoding in the byte array's values.

Related

Android studio - byte operations - changing value

I have a problem with bit operations
int progress = slider.getProgress(); value of user input
then I have to do shift left and change it to HEX
int shl = 1<<progress-1;
String hexStr = Integer.toHexString(shl);
Nex Im sending bytes by BT
byte bit = Byte.decode(hexStr)
command[2]=bit;
Now the problem
If user set for example 2 it is ok 0b100 = 0x04
But if user set 5 0b10000 = hexStr = 10 in command[2] it gets value 0x0A
Why is it changing value?
"But if user set 5 0b10000 = hexStr = 10 in command[2] it gets value = 0x0A.
Why is it changing value?"
It is correct. What different result are you expecting?
For example : If progress is 5 then...
Doing bit shift like 1 << progress-1 == 1 << 4 = (resulting bits= 0001 0000) which gives :
int shl = 10 in hex format or even int shl = 16 in decimal format
Doing String hexStr = Integer.toHexString(shl); puts shl's "10" hex string value to the other string hexStr (ie: is also now a "10")...
Doing byte bit = Byte.decode(hexStr) makes a byte with a decimal value of hexStr's "10".
This is how your result is command[2] saying hex value of 0x0A which == decimal value of 10.
....
"I'm not translating decimal to binary or hex, but the user input which tells on which position "1" should go. Hope it's clear..."
Why not just write "1" and then add as many zeroes as required (padding)?
Note: I'm not sure what value command[2]= is supposed to get. Maybe it checks the 8 bits of that byte, or maybe it expects a number (integer). It's confusng becuase your numbers rely on "1 followed by zeroes", also binary can be "1 followed by zeroes"
Binary : There are 8 bits in a byte, so the max binary you can send is 10000000 only.
Integer : A single byte is signed so the max value s 128. By this logic your options are 1, 10, 100 only.
See if this helps (check which command[2]= you want. I've commented // them out for now) :
int progress = 5;
int shl = 1 << progress-1; //why??
String hexStr = Integer.toHexString(shl);
String shlStr = Integer.toString(shl);
String zeroStr = "";
byte bit = Byte.decode(hexStr);
//command[2]=bit;
System.out.println("shl result string : " + shlStr);
System.out.println("Bytes string hex : " + hexStr);
//# Padding
for(int i = 0; i < (progress-1); i++)
{ zeroStr += "0"; }
shlStr = "1" + zeroStr;
//command[2]= Byte.decode(shlStr);
System.out.println("Result string hex : " + zeroStr);
System.out.println("shi padding string : " + shiStr);

Why am i getting 3 bytes instead 1 byte after hexadecimal/string/byte conversion in java?

I have this program:
String hexadecimal = "AF";
byte decimal[] = new byte[hexadecimal.length()/2];
int j = 0;
for ( int i = 0; i < decimal.length; i++)
{
decimal[i] = (byte) Integer.parseInt(hexadecimal.substring(j,j+2),16); //Maybe the problem is this statement
j = j + 2;
}
String s = new String(decimal);
System.out.println("TOTAL LEN: " + s.length());
byte aux[] = s.getBytes();
System.out.println("TOTAL LEN: " + aux.length);
The first total is "1" and the second one is "3", i thought i would will get "1" in the second total. Why is happen this? My intention is generate another hexadecimal string with the same value as the original string (AF), but i am having this issue.
Regards!
P.D. Sorry for my english, let me know if i explained myself well.
Don't know what exactly you try to achieve. But find below what you are doing.
Integer.parseInt(hexadecimal.substring(j, j + 2), 16) returns 175
(byte) 175 is -81
new String(decimal) tries to create an String from this byte array related to your current character set (probably it's UTF-8)
As the byte array does not contain a valid representation of UTF-8 bytes the created String contains the "REPLACEMENT CHARACTER" for the Unicode codepoint U+FFFD. The UTF-8 byte representation for this codepoint is EF BF BD (or -17 -65 -67). That's why the second length is three.
Have a look here Wikipedia UTF-8. Any character with a codepoint <= 7F can be represented by a single byte. For all other characters the first byte must have the bits 7 and 6 set 11....... Which is not the case for the value -81 which is 10101111. There for this is not a valid codepoint and it's replaced with the "REPLACEMENT CHARACTER".

Using 'printf' in Java

I am having problems implementing the printf method into my code. I started my first Java course this week and am trying to get ahead of the class. Essentially, I am to create an output of ASCII characters, hexadecimal numbers, and their decimal equivalents, up to 127 entries. The number of rows created in the output is chosen by user input. This is the code I have so far:
package lab1;
import java.util.Scanner;
public class Lab1 {
public static void main(String[] args) {
//declare
Scanner scan = new Scanner(System.in);
//prompt the user to enter an integer, num defines the # of rows displayed in output
System.out.print("How many groups? ");
int num = scan.nextInt();
//print ascii, then hex value, then dec value
for (int c = 0; c < 128; c++) {
String hex = Integer.toString(c , 16);
String output = (char)c + " " + hex + " " + c;
System.out.println(output);
/*
//print the output with printf to create the columns
//character (c), string(s), decimal integer(d)
System.out.printf("%-2c %-2s %-2d", output);
*/
}
}
}
I would have posted an image here showing what the final result should look like but I need 10 reputation. I am able to email a copy to you privately though.
I hope you can help me understand how to accomplish this, or direct me to a resource where I am able to learn myself.
Thanks!
You need to pass the same number of arguments as you have flags in your printf.
for (int c = 0; c < 128; c++) {
// String hex = Integer.toString(c , 16); - No need for this anymore.
// Print the output with printf to create the columns
// character (c), string(s), decimal integer(d)
System.out.printf("%-2c 0x%-2X %-2d%n", (char)c, c, c);
}
With 0x%-2X, you can print out uppercase Hex values. I added 0x as a prefix to specify the base.
Example output:
...
A 0x41 65
B 0x42 66
C 0x43 67
D 0x44 68
E 0x45 69
F 0x46 70
G 0x47 71
H 0x48 72
I 0x49 73
J 0x4A 74
K 0x4B 75
L 0x4C 76
M 0x4D 77
N 0x4E 78
O 0x4F 79
P 0x50 80
Q 0x51 81
R 0x52 82
S 0x53 83
T 0x54 84
U 0x55 85
V 0x56 86
W 0x57 87
X 0x58 88
Y 0x59 89
Z 0x5A 90
...
You don't actually need to pass multiple arguments.
for (int c = 0; c < 128; c++) {
// Print ASCII, then hex, then dec
System.out.printf("%1$-2c %1$-2x %1$-2d%n", c);
}
See the docs here: http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html
The problem is you need three arguments for you printf, one each for char, String and decimal. Since you are passing only one variable (which is of type String) it gets confused. Remember, concatenating everything in one String(output) makes all a type String.
You need each tag to correspond with a variable, and your tags need to be formatted correctly.
To print an ascii, hex, and decimal value, your printf statement should look something like this:
System.out.printf("%-2c - %-2x - %-2f", someChar, someHex, someFloat);
where someChar is a char, someHex is an int whose hex value you wish to display, and someFloat is the float/double value you wish to display.
For more information on format strings in Java see: http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html

Convert int which start with leading zero to string

I'm trying to convert int's which start with 0 to strings to be stored in a phone directory as the telephone numbers can start with 0.
I've tried -
int num = 0125;
String.format("%04d",num);
and
Integer.toString(num);
and
DecimalFormat df = new DecimalFormat("0000");
df.format(num);
Each time I get the output 0085 rather than 0125.
How do I convert an int with a leading zero to a string in decimal format?
An int value starting with a zero is considered to be a octal number (having numbers from 0 - 7) similar to hexadecimal numbers. Hence your value:
0125
is equal to: 1 * 82 + 2 * 81 + 5 * 80 == 64 + 16 + 5 == 85
Don't try to represent a phone-number as an int. Instead use a String and validate it using a regex expression. If you combine both, you may as well represent a phone number by its own type like:
public class PhoneNumber {
private final String number;
public PhoneNumber(String number) {
if (number == null || !number.matches("\\d+([-]\\d+)?")) {
throw new .....
}
this.number = number;
}
}
The regex is just an example matching phone numbers like: 1234 or 0123-45678.
A numeric literal that starts with 0 is considered to be Octal (base 8). 125 base 8 is 85 base 10 (decimal).
Also, int i = 09 will throw a compiler error for the same reason.
See 09 is not recognized where as 9 is recognized
0125 is actually 85. Why?
Numbers that starts with 0, are octal numbers. So 0125 is:
5*80 + 2*81 + 1*82 = 85
See the JLS - 3.10.1. Integer Literals:
An octal numeral consists of an ASCII digit 0 followed by one or more
of the ASCII digits 0 through 7 interspersed with underscores, and can
represent a positive, zero, or negative integer.

Java int issue while intializtion

I have been working on a project and i saw some references on web and they initialized :
int val= 0x000; output 0
int val1= 0x001; output 1
How exactly java is converting this?
Thanks
It's an hexadecimal (base 16 instead of base 10). Hexadecimals starts with 0x.... And it can contain these digits: 0123456789ABCDEF
Octals (base 8) starts with 0... and can containt digits less than 8 (01234567)
int dec = 123; // decimal: 1*(10^2) + 2*(10^1) + 3*(10^0) = 123
int oct = 0123; // octal: 1*(8^2) + 2*(8^1) + 3*(8^0) = 83
int hex = 0x123; // hexadecimal: 1*(16^2) + 2*(16^1) + 3*(16^0) = 291
You can do int val = 0; and int val = 1; with decimal notation..
The 0x before the number indicate an hexadecimal notation...
All notations are:
0b to binary: int i = 0b10101010110;
nothing to decimal: int i = 123;
0 to octal: int i = 0123345670;
0x to hexadecimal: int i = 0xAEF123;
As a matter of fact, Java does not "convert" but "interpret" the values (as hexadecimal).
Numbers starting with 0x are hexadecimal. Java converts them (like decimal ones, too) to binary and saves them.
This hexadecimal number system (base 16)
Start with 0x...
(Octals start with 0...)
Link

Categories