Just use BinaryCodec from Apache Commons:
byte[] bytes = new BinaryCodec().toByteArray("1000000111010000");
If you want to do such conversion on your own, your code needs some corrections.
You are expecting that A.charAt(i) will return numeric 0 or 1, but will actually return char '0' or '1'. The char data type is a single 16-bit Unicode character with a numeric range from 0 to 2^16, it's values are formally called code points.
To print the code point value you need to cast char to int:
System.out.println("Character " + A.charAt(i) + " has a code point numeric value of " + (int)A.charAt(i));
Output for '0' and '1':
Character 0 has a code point numeric value of 48
Character 1 has a code point numeric value of 49
Operator '<<' converts char operands to int, therefore this shifting is producing wrong results because:
firstByte = (byte) (firstByte | (A.charAt(i) << i));
is the same as
firstByte = (byte) (firstByte | ( (int)A.charAt(i) << i));
which for char '0' is the same as shifting value 48 to the left:
firstByte = (byte) (firstByte | ( 48 << i));
To convert char '0' or '1' to 0 or 1 numeric value use Character.getNumericValue(A.charAt(i)):
firstByte = (byte) (firstByte | ( Character.getNumericValue(A.charAt(i)) << i));
Also shifting by value i is incorrect. You need to shift by (7-i) for the first byte or (7-i%8) for the second byte. When index i reaches 8 it needs to start counting from 0, therefore i%8
When printing a values for a byte type you have two options: byte numeric value or binary string representation:
System.out.println("FIRST byte numeric value = " + xByte[0] + ", binary string representation = " + Integer.toBinaryString((xByte[0]+256)%256));
System.out.println("SECOND byte numeric value = " + xByte[1] + ", binary string representation = " + Integer.toBinaryString((xByte[1]+256)%256));
output:
FIRST byte value = -127, binary representation = 10000001
SECOND byte value = -48, binary representation = 11010000
Whole corrected example:
public class ByteTest
{
public static void main(String[] args)
{
byte firstByte=0;
byte secondByte=0;
String A = "1000000111010000";
byte[] xByte = new byte[2];
for(int i=0 ; i<A.length() ;i++){
System.out.println("Character " + A.charAt(i) + " has a code point numeric value of " + (int)A.charAt(i));
if(i<8){
System.out.println(" i : "+i+" A.char[i] :"+A.charAt(i));
firstByte = (byte) (firstByte | (Character.getNumericValue(A.charAt(i)) << (7-i)));
}else{
System.out.println(" i : "+i+" A.char[i] :"+A.charAt(i));
secondByte = (byte) (secondByte | (Character.getNumericValue(A.charAt(i)) << (7-i%8)));
}
}
xByte[0] = firstByte;
xByte[1] = secondByte;
System.out.println("FIRST byte numeric value = " + xByte[0] + ", binary string representation = " + Integer.toBinaryString((xByte[0]+256)%256));
System.out.println("SECOND byte numeric value = " + xByte[1] + ", binary string representation = " + Integer.toBinaryString((xByte[1]+256)%256));
}
}
Answer from Sergej Panic on Stack OverflowJust use BinaryCodec from Apache Commons:
byte[] bytes = new BinaryCodec().toByteArray("1000000111010000");
If you want to do such conversion on your own, your code needs some corrections.
You are expecting that A.charAt(i) will return numeric 0 or 1, but will actually return char '0' or '1'. The char data type is a single 16-bit Unicode character with a numeric range from 0 to 2^16, it's values are formally called code points.
To print the code point value you need to cast char to int:
System.out.println("Character " + A.charAt(i) + " has a code point numeric value of " + (int)A.charAt(i));
Output for '0' and '1':
Character 0 has a code point numeric value of 48
Character 1 has a code point numeric value of 49
Operator '<<' converts char operands to int, therefore this shifting is producing wrong results because:
firstByte = (byte) (firstByte | (A.charAt(i) << i));
is the same as
firstByte = (byte) (firstByte | ( (int)A.charAt(i) << i));
which for char '0' is the same as shifting value 48 to the left:
firstByte = (byte) (firstByte | ( 48 << i));
To convert char '0' or '1' to 0 or 1 numeric value use Character.getNumericValue(A.charAt(i)):
firstByte = (byte) (firstByte | ( Character.getNumericValue(A.charAt(i)) << i));
Also shifting by value i is incorrect. You need to shift by (7-i) for the first byte or (7-i%8) for the second byte. When index i reaches 8 it needs to start counting from 0, therefore i%8
When printing a values for a byte type you have two options: byte numeric value or binary string representation:
System.out.println("FIRST byte numeric value = " + xByte[0] + ", binary string representation = " + Integer.toBinaryString((xByte[0]+256)%256));
System.out.println("SECOND byte numeric value = " + xByte[1] + ", binary string representation = " + Integer.toBinaryString((xByte[1]+256)%256));
output:
FIRST byte value = -127, binary representation = 10000001
SECOND byte value = -48, binary representation = 11010000
Whole corrected example:
public class ByteTest
{
public static void main(String[] args)
{
byte firstByte=0;
byte secondByte=0;
String A = "1000000111010000";
byte[] xByte = new byte[2];
for(int i=0 ; i<A.length() ;i++){
System.out.println("Character " + A.charAt(i) + " has a code point numeric value of " + (int)A.charAt(i));
if(i<8){
System.out.println(" i : "+i+" A.char[i] :"+A.charAt(i));
firstByte = (byte) (firstByte | (Character.getNumericValue(A.charAt(i)) << (7-i)));
}else{
System.out.println(" i : "+i+" A.char[i] :"+A.charAt(i));
secondByte = (byte) (secondByte | (Character.getNumericValue(A.charAt(i)) << (7-i%8)));
}
}
xByte[0] = firstByte;
xByte[1] = secondByte;
System.out.println("FIRST byte numeric value = " + xByte[0] + ", binary string representation = " + Integer.toBinaryString((xByte[0]+256)%256));
System.out.println("SECOND byte numeric value = " + xByte[1] + ", binary string representation = " + Integer.toBinaryString((xByte[1]+256)%256));
}
}
You can't simply cast the A.charAt(i) to an int. It'll return the ASCII code of the 1 and 0.
Therefore, you need to do something like this to get their numeric value:-
int bit = Character.getNumericValue(A.charAt(i)); // This will give the actual value
...
firstByte = (byte) (firstByte | (bit << i));
Byte has a (signed) range from -128 to 127, where as int has a (also signed) range of −2,147,483,648 to 2,147,483,647.
What it means is that since the values you're going to use will always be between that range, by using the byte type you're telling anyone reading your code this value will be at most between -128 to 127 always without having to document about it.
Still, proper documentation is always key and you should only use it in the case specified for readability purposes, not as a replacement for documentation.
If you're using a variable which maximum value is 127 you can use byte instead of int so others know without reading any if conditions after, which may check the boundaries, that this variable can only have a value between -128 and 127.
So it's kind of self-documenting code - as mentioned in the text you're citing.
Personally, I do not recommend this kind of "documentation" - only because a variable can only hold a maximum value of 127 doesn't reveal it's really purpose.
A byte is 8 bits. 2^8 is 256, meaning that 8 bits can store 256 distinct values. In Java, those values are the numbers in the range -128 to 127, so 87 is a valid byte, as it is in that range.
Similarly, try doing something like byte x = 200, and you will see that you get an error, as 200 is not a valid byte.
A byte is just an 8-bit integer value. Which means it can hold any value from -2^7 to 2^7-1, which includes all of the number in {87, 79, 87, 46, 46, 46}.
An integer in java, is just a 4-byte integer, allowing it to hold -2^31 to 2^31 - 1
You cannot. A basic numeric constant is considered an integer (or long if followed by a "L"), so you must explicitly downcast it to a byte to pass it as a parameter. As far as I know there is no shortcut.
You have to cast, I'm afraid:
f((byte)0);
I believe that will perform the appropriate conversion at compile-time instead of execution time, so it's not actually going to cause performance penalties. It's just inconvenient :(