How to transform hexadecimal string into Byte. Java - java

My problem is that I've to write a code where a MAC direction must be written via keyboard and then, the code must recognize it to mount a "Magic Packet".
Let me show some code so you can understand better my problem and maybe reach some solution.
static String realMAC[] = new String [6];
static String mac; //that's the written string
private DatagramPacket buildWOLPacket(InetAddress address,String MAC) {
String splittedMAC[] = new String[12];
final int SIZE = 6 + 6 * 16; // See above for this magic number
byte data[] = new byte[SIZE];
for (int i = 0; i < 6; i++) {
data[i] = (byte) 0xff;
}
//Method where each character written
//is stored into a char array (realMAC[])
for (int i = 0 ; i<12; i++) {
String replacedMAC = MAC.replace(":", ""); //Here I delete all the : from the MAC adress introduced via keyboard.
if (i == 12)
splittedMAC[i] = replacedMAC.substring(i,(i));
else splittedMAC[i] = replacedMAC.substring(i,(i+1));}
And now the piece of code that is giving me problems
//All the (byte) 0x00 and so on are examples of a MAC direction and how to convert it if it is predefined
data[6 * i + 0] = Byte.parseByte(realMAC[0]); //(byte) 0x00;
data[6 * i + 1] = Byte.parseByte(realMAC[1]); //(byte) 0x1A;
data[6 * i + 2] = Byte.parseByte(realMAC[2]); //(byte) 0x09;
data[6 * i + 3] = Byte.parseByte(realMAC[3]); //(byte) 0x07;
data[6 * i + 4] = Byte.parseByte(realMAC[4]); //(byte) 0x8c;
data[6 * i + 5] = Byte.parseByte(realMAC[5]); //(byte) 0xe9;
My problem comes when converting the realMAC[] into bytes because of the x and letters from (0x8c, for example) because parseByte only accepts ints and ascii code. How could I tranform that string in hex form into bits?
Thank you so much.

Byte also has a .parseByte() method taking a radix as an argument. However that won't account for the initial 0x so you have to use substring(). Do:
Byte.parseByte(realMac[0].substring(2), 16)
//etc etc
More generally, all "numeric integral" classes (Integer, Short, Long) have such a method.

Byte.decode accepts a String that may begin with 0x or 0X. (It may also parse a decimal or octal number depending on what the string looks like.)

Related

Set audio sample bit depth in Java

Here is my code. I am using javax.sound.sampled.* for the audio classes.
byte[] myAudioByteArray = new byte[]{0, 127, 127, 127, -127, 127};
ByteArrayInputStream bais = new ByteArrayInputStream(myAudioByteArray);
AudioInputStream stream = new AudioInputStream(bais, new AudioFormat(SampleRate.R_44100, 24, 1, true, false), myAudioByteArray.length)
The amplitude is bitdepth, so how does java allow you to set the bitdepth of a each sample?
I have set the bit depth of the resulting file to be 24 bit depth, so in theory I should be able to set the samples at the specific depth range (16,777,216).
The problem is I don't know how you do this with the bytes you feed into the ByteArrayInputStream object that then goes into the AudioInputStream object because they are signed.
I thought maybe you could convert the bytes to their binary representation and then combine 3 of them to get 3 bytes for the 16,777,216 range, but that theory is incorrect from what I can tell.
I thought maybe you could convert the bytes to their binary representation and then combine 3 of them to get 3 bytes for the 16,777,216 range, but that theory is incorrect from what I can tell.
Not sure, why this didn't work for you.
Each sample has to be encoded, either big endian or little endian. Here are some methods from the audio processing library jipes that show how you can decode bytes to samples from either little or big endian to int:
private static int byteToIntLittleEndian(final byte[] buf, final int offset, final int bytesPerSample) {
int sample = 0;
for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
final int aByte = buf[offset + byteIndex] & 0xff;
sample += aByte << 8 * (byteIndex);
}
return sample;
}
private static int byteToIntBigEndian(final byte[] buf, final int offset, final int bytesPerSample) {
int sample = 0;
for (int byteIndex = 0; byteIndex < bytesPerSample; byteIndex++) {
final int aByte = buf[offset + byteIndex] & 0xff;
sample += aByte << (8 * (bytesPerSample - byteIndex - 1));
}
return sample;
}
Once the value is decoded you still have to cast to your target interval. If you were interested in a 2 bytes format, i.e. bit depth of 16, you'd simply do this:
final int sample = byteToIntLittleEndian(buf, sampleOffset, bytesPerChannel);
final short shortSample = (short)sample;
The cast takes care of the overflow.
With 3 bytes it's a little more complicated. You need to know the value range first. Note that because you are interested in signed values, it's not [0,2^24], but:
/**
* A constant holding the minimum value a <code>signed24bit</code> can
* have, -2<sup>22</sup>.
*/
private static final int MIN_VALUE_24BIT = -2 << 22;
/**
* A constant holding the maximum value a <code>signed24bit</code> can
* have, 2<sup>22</sup>-1.
*/
private static final int MAX_VALUE_24BIT = -MIN_VALUE_24BIT-1;
Then you use that to convert to a signed sample value like this:
final int sample = byteToIntLittleEndian(bud, sampleOffset, bytesPerChannel);
final int threeByteSample = sample > MAX_VALUE_24BIT ? sample + MIN_VALUE_24BIT + MIN_VALUE_24BIT : sample;

Padding Binary Output with 0's [duplicate]

for example, for 1, 2, 128, 256 the output can be (16 digits):
0000000000000001
0000000000000010
0000000010000000
0000000100000000
I tried
String.format("%16s", Integer.toBinaryString(1));
it puts spaces for left-padding:
` 1'
How to put 0s for padding. I couldn't find it in Formatter. Is there another way to do it?
P.S. this post describes how to format integers with left 0-padding, but it is not for the binary representation.
I think this is a suboptimal solution, but you could do
String.format("%16s", Integer.toBinaryString(1)).replace(' ', '0')
There is no binary conversion built into the java.util.Formatter, I would advise you to either use String.replace to replace space character with zeros, as in:
String.format("%16s", Integer.toBinaryString(1)).replace(" ", "0")
Or implement your own logic to convert integers to binary representation with added left padding somewhere along the lines given in this so.
Or if you really need to pass numbers to format, you can convert your binary representation to BigInteger and then format that with leading zeros, but this is very costly at runtime, as in:
String.format("%016d", new BigInteger(Integer.toBinaryString(1)))
Here a new answer for an old post.
To pad a binary value with leading zeros to a specific length, try this:
Integer.toBinaryString( (1 << len) | val ).substring( 1 )
If len = 4 and val = 1,
Integer.toBinaryString( (1 << len) | val )
returns the string "10001", then
"10001".substring( 1 )
discards the very first character. So we obtain what we want:
"0001"
If val is likely to be negative, rather try:
Integer.toBinaryString( (1 << len) | (val & ((1 << len) - 1)) ).substring( 1 )
You can use Apache Commons StringUtils. It offers methods for padding strings:
StringUtils.leftPad(Integer.toBinaryString(1), 16, '0');
I was trying all sorts of method calls that I haven't really used before to make this work, they worked with moderate success, until I thought of something that is so simple it just might work, and it did!
I'm sure it's been thought of before, not sure if it's any good for long string of binary codes but it works fine for 16Bit strings. Hope it helps!! (Note second piece of code is improved)
String binString = Integer.toBinaryString(256);
while (binString.length() < 16) { //pad with 16 0's
binString = "0" + binString;
}
Thanks to Will on helping improve this answer to make it work with out a loop.
This maybe a little clumsy but it works, please improve and comment back if you can....
binString = Integer.toBinaryString(256);
int length = 16 - binString.length();
char[] padArray = new char[length];
Arrays.fill(padArray, '0');
String padString = new String(padArray);
binString = padString + binString;
A simpler version of user3608934's idea "This is an old trick, create a string with 16 0's then append the trimmed binary string you got ":
private String toBinaryString32(int i) {
String binaryWithOutLeading0 = Integer.toBinaryString(i);
return "00000000000000000000000000000000"
.substring(binaryWithOutLeading0.length())
+ binaryWithOutLeading0;
}
I do not know "right" solution but I can suggest you a fast patch.
String.format("%16s", Integer.toBinaryString(1)).replace(" ", "0");
I have just tried it and saw that it works fine.
Starting with Java 11, you can use the repeat(...) method:
"0".repeat(Integer.numberOfLeadingZeros(i) - 16) + Integer.toBinaryString(i)
Or, if you need 32-bit representation of any integer:
"0".repeat(Integer.numberOfLeadingZeros(i != 0 ? i : 1)) + Integer.toBinaryString(i)
try...
String.format("%016d\n", Integer.parseInt(Integer.toBinaryString(256)));
I dont think this is the "correct" way to doing this... but it works :)
I would write my own util class with the method like below
public class NumberFormatUtils {
public static String longToBinString(long val) {
char[] buffer = new char[64];
Arrays.fill(buffer, '0');
for (int i = 0; i < 64; ++i) {
long mask = 1L << i;
if ((val & mask) == mask) {
buffer[63 - i] = '1';
}
}
return new String(buffer);
}
public static void main(String... args) {
long value = 0b0000000000000000000000000000000000000000000000000000000000000101L;
System.out.println(value);
System.out.println(Long.toBinaryString(value));
System.out.println(NumberFormatUtils.longToBinString(value));
}
}
Output:
5
101
0000000000000000000000000000000000000000000000000000000000000101
The same approach could be applied to any integral types. Pay attention to the type of mask
long mask = 1L << i;
A naive solution that work would be
String temp = Integer.toBinaryString(5);
while (temp.length() < Integer.SIZE) temp = "0"+temp; //pad leading zeros
temp = temp.substring(Integer.SIZE - Short.SIZE); //remove excess
One other method would be
String temp = Integer.toBinaryString((m | 0x80000000));
temp = temp.substring(Integer.SIZE - Short.SIZE);
This will produce a 16 bit string of the integer 5
// Below will handle proper sizes
public static String binaryString(int i) {
return String.format("%" + Integer.SIZE + "s", Integer.toBinaryString(i)).replace(' ', '0');
}
public static String binaryString(long i) {
return String.format("%" + Long.SIZE + "s", Long.toBinaryString(i)).replace(' ', '0');
}
This is an old trick, create a string with 16 0's then append the trimmed binary string you got from String.format("%s", Integer.toBinaryString(1)) and use the right-most 16 characters, lopping off any leading 0's. Better yet, make a function that lets you specify how long of a binary string you want. Of course there are probably a bazillion other ways to accomplish this including libraries, but I'm adding this post to help out a friend :)
public class BinaryPrinter {
public static void main(String[] args) {
System.out.format("%d in binary is %s\n", 1, binaryString(1, 4));
System.out.format("%d in binary is %s\n", 128, binaryString(128, 8));
System.out.format("%d in binary is %s\n", 256, binaryString(256, 16));
}
public static String binaryString( final int number, final int binaryDigits ) {
final String pattern = String.format( "%%0%dd", binaryDigits );
final String padding = String.format( pattern, 0 );
final String response = String.format( "%s%s", padding, Integer.toBinaryString(number) );
System.out.format( "\npattern = '%s'\npadding = '%s'\nresponse = '%s'\n\n", pattern, padding, response );
return response.substring( response.length() - binaryDigits );
}
}
This method converts an int to a String, length=bits. Either padded with 0s or with the most significant bits truncated.
static String toBitString( int x, int bits ){
String bitString = Integer.toBinaryString(x);
int size = bitString.length();
StringBuilder sb = new StringBuilder( bits );
if( bits > size ){
for( int i=0; i<bits-size; i++ )
sb.append('0');
sb.append( bitString );
}else
sb = sb.append( bitString.substring(size-bits, size) );
return sb.toString();
}
You can use lib https://github.com/kssource/BitSequence. It accept a number and return bynary string, padded and/or grouped.
String s = new BitSequence(2, 16).toBynaryString(ALIGN.RIGHT, GROUP.CONTINOUSLY));
return
0000000000000010
another examples:
[10, -20, 30]->00001010 11101100 00011110
i=-10->00000000000000000000000000001010
bi=10->1010
sh=10->00 0000 0000 1010
l=10->00000001 010
by=-10->1010
i=-10->bc->11111111 11111111 11111111 11110110
for(int i=0;i<n;i++)
{
for(int j=str[i].length();j<4;j++)
str[i]="0".concat(str[i]);
}
str[i].length() is length of number say 2 in binary is 01 which is length 2
change 4 to desired max length of number. This can be optimized to O(n).
by using continue.
import java.util.Scanner;
public class Q3{
public static void main(String[] args) {
Scanner scn=new Scanner(System.in);
System.out.println("Enter a number:");
int num=scn.nextInt();
int numB=Integer.parseInt(Integer.toBinaryString(num));
String strB=String.format("%08d",numB);//makes a 8 character code
if(num>=1 && num<=255){
System.out.println(strB);
}else{
System.out.println("Number should be in range between 1 and 255");
}
}
}

wrong output of CRC32 in android

I'm calculating CRC32 like code below :
import java.util.zip.CRC32;
String data = "99D5503012013165411";
byte bytes[] = data.getBytes();
Checksum checksum = new CRC32();
checksum.update(bytes, 0, bytes.length);
long checksumValue = checksum.getValue();
System.out.println("Result of CRC32 : " +Long.toHexString(checksumValue) + " !");
when I compare my code with this online CRC32 calculation it only gives me the right result when the Input type ASCII, So there is a way to have the same result as Hex?
Your problem is how you create the input (byte bytes[] = ...).
The String#getBytes method returns byte representation of individual characters in the string. But I suppose the input string 99D5503012013165411 is a hex representation of byte array.
So you have to convert it to bytes like here.
One byte is represented by two characters: see Hexadecimal on Wiki.
Update: There is another catch. One hex letter is 4bits, thus it is half of byte. A proper byte array written as hex string should be of even length.
This adds another level of confusion, since your example input is 19 chars long.
Working solution is (that gives output same as the online calc):
public static void main(String[] args)
{
String data = "99D55030120131654101"; // notice the 01 at the end
byte bytes[] = hexStringToByteArray(data);
Checksum checksum = new CRC32();
checksum.update(bytes, 0, bytes.length);
long checksumValue = checksum.getValue();
System.out.println("Result of CRC32 : " +Long.toHexString(checksumValue) + " !");
// prints: Result of CRC32 : 9671cb4a !
}
// took from https://stackoverflow.com/a/140861/6749977 :
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
The online tool you linked handles the missing letter by interpreting the last 1 as 01 (I had to change the input experimentally there). So I had to change the input to be of even length...
If you are going to get really input like this, and you are sure you want to handle the case this way, the hexStringToByteArray procedure should be updated. But be careful, I thing the right way would be to prepend the whole string with zeros to have even-length. Like an base-10 analogy: 132==0123
Update 2: Based on your comment here I add a solution with modified hexStringToByteArray method (even tough I feel a bit like doing your homework for you):
public static void main(String[] args)
{
String data = "99D5503012013165411";
String dataOnlyHexChars = data.replaceAll("[^0-9a-fA-F]", ""); // not very cool
byte bytes[] = hexStringToByteArray(dataOnlyHexChars);
Checksum checksum = new CRC32();
checksum.update(bytes, 0, bytes.length);
long checksumValue = checksum.getValue();
System.out.println("Result of CRC32 : " +Long.toHexString(checksumValue) + " !");
// prints: Result of CRC32 : 9671cb4a !
}
// took from https://stackoverflow.com/a/140861/6749977 and changed a bit :
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[(len + 1) / 2]; // changed
for (int i = 0; i < len; i += 2) {
if (len==i + 1) // changed
data[i / 2] = (byte) Character.digit(s.charAt(i), 16);
else
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

Hex digit to binary with only 4 digits

int[] LETTERS = {0x69F99}
I want to convert every single hex digit to binary, for example the 1st hex digit from the 1st hex string (6):
String hex = Integer.toHexString(LETTERS[0]);
String binary = Integer.toBinaryString(hex.charAt(0));
System.out.println(binary);
OUTPUT:110110
If I do this Integer.toBinaryString(6) the output will be 110, but I want something with 4 digits, is it possible?
I'd just pad the string as appropriate with your favorite library or a utility function.
With Guava:
String binary = Strings.padStart(Integer.toBinaryString(hex.charAt(0)), 4, '0'));
Another option would be to simply fill a character buffer and render it as a string, which is essentially what the OpenJDK implementation does:
public static String intToBin(int num) {
char[] buf = new char[4];
buf[0] = num & 0x1;
buf[1] = num & 0x2;
buf[2] = num & 0x4;
buf[3] = num & 0x8;
return new String(buf);
}
You have no string here - just an array with one int so you essentially try to convert this integer into nibbles and this can be done this way:
int num = 0x12345678;
String bin32 = String.format("%32s", Integer.toBinaryString(num)).replace(" ", "0");
System.out.printf("all 32bits=[%s]\n", bin32);
for(int nibble = 0; nibble < 32; nibble += 4)
{
System.out.printf("nibble[%d]=[%s]\n", nibble, bin32.subSequence(nibble, nibble+4));
}
gives:
all 32bits=[00010010001101000101011001111000]
nibble[0]=[0001] ie hex digit 1 as bin
nibble[4]=[0010] ie hex digit 2 as bin
nibble[8]=[0011]
nibble[12]=[0100]
nibble[16]=[0101]
nibble[20]=[0110]
nibble[24]=[0111]
nibble[28]=[1000] ie hex digit 8 as bin

Integer to two digits hex in Java

I need to change a integer value into 2-digit hex value in Java.Is there any way for this.
Thanks
My biggest number will be 63 and smallest will be 0.
I want a leading zero for small values.
String.format("%02X", value);
If you use X instead of x as suggested by aristar, then you don't need to use .toUpperCase().
Integer.toHexString(42);
Javadoc: http://docs.oracle.com/javase/6/docs/api/java/lang/Integer.html#toHexString(int)
Note that this may give you more than 2 digits, however! (An Integer is 4 bytes, so you could potentially get back 8 characters.)
Here's a bit of a hack to get your padding, as long as you are absolutely sure that you're only dealing with single-byte values (255 or less):
Integer.toHexString(0x100 | 42).substring(1)
Many more (and better) solutions at Left padding integers (non-decimal format) with zeros in Java.
String.format("%02X", (0xFF & value));
Use Integer.toHexString(). Dont forget to pad with a leading zero if you only end up with one digit. If your integer is greater than 255 you'll get more than 2 digits.
StringBuilder sb = new StringBuilder();
sb.append(Integer.toHexString(myInt));
if (sb.length() < 2) {
sb.insert(0, '0'); // pad with leading zero if needed
}
String hex = sb.toString();
If you just need to print them try this:
for(int a = 0; a < 255; a++){
if( a % 16 == 0){
System.out.println();
}
System.out.printf("%02x ", a);
}
i use this to get a string representing the equivalent hex value of an integer separated by space for every byte
EX : hex val of 260 in 4 bytes = 00 00 01 04
public static String getHexValString(Integer val, int bytePercision){
StringBuilder sb = new StringBuilder();
sb.append(Integer.toHexString(val));
while(sb.length() < bytePercision*2){
sb.insert(0,'0');// pad with leading zero
}
int l = sb.length(); // total string length before spaces
int r = l/2; //num of rquired iterations
for (int i=1; i < r; i++){
int x = l-(2*i); //space postion
sb.insert(x, ' ');
}
return sb.toString().toUpperCase();
}
public static void main(String []args){
System.out.println("hex val of 260 in 4 bytes = " + getHexValString(260,4));
}
According to GabrielOshiro, If you want format integer to length 8, try this
String.format("0x%08X", 20) //print 0x00000014

Categories