Parse signed Byte from binary | Java - java

I have the following problem in Java. I am using an encryption algorithm that can produce negative bytes as outcome, and for my purposes I must be able to deal with them in binary. For negative bytes, the first or most significant bit in the of the 8 is 1. When I am trying to convert binary strings back to bytes later on, I am getting a NumberFormatException because my byte is too long. Can I tell Java to treat it like an unsigned byte and end up with negative bytes? My code so far is this:
private static String intToBinByte(int in) {
StringBuilder sb = new StringBuilder();
sb.append("00000000");
sb.append(Integer.toBinaryString(in));
return sb.substring(sb.length() - 8);
}
intToBinByte(-92); // --> 10100100
Byte.parseByte("10100100", 2) // --> NumberFormatException
Value out of range. Value:"10100100" Radix:2
Is there a better way to parse signed Bytes from binary in Java?
Thanks in advance!

You can just parse it with a larger type, then cast it to byte. Casting simply truncates the number of bits:
byte b = (byte) Integer.parseInt("10100100", 2);

I have written the following function to solve the problem:
private static byte binStringToByte(String in) {
byte ret = Byte.parseByte(in.substring(1), 2);
ret -= (in.charAt(0) - '0') * 128;
return ret;
}

Related

Convert from hex to int and vice versa in java

I have next method for converting to int from hex:
public static byte[] convertsHexStringToByteArray2(String hexString) {
int hexLength = hexString.length() / 2;
byte[] bytes = new byte[hexLength];
for (int i = 0; i < hexLength; i++) {
int hex = Integer.parseInt(hexString.substring(2 * i, 2 * i + 2), 16);
bytes[i] = (byte) hex;
}
return bytes;
}
when I use it for "80" hex string I get strange, not expected result:
public static void main(String[] args) {
System.out.println(Arrays.toString(convertsHexStringToByteArray2("80"))); // gives -128
System.out.println(Integer.toHexString(-128));
System.out.println(Integer.toHexString(128));
}
the output:
[-128]
ffffff80
80
I expect that "80" will be 128. What is wrong with my method?
I have next method for converting to int from hex
The method you posted converts a hex String to a byte array, and not to an int. That's why it is messing with its sign.
Converting from hex to int is easy:
Integer.parseInt("80", 16)
$1 ==> 128
But if you want to get a byte array for further processing by just casting:
(byte) Integer.parseInt("80", 16)
$2 ==> -128
It "changes" its sign. For further information on primitives and signed variable types take a look at Primitive Data Types, where it says:
The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
One could easily invert the sign by just increasing the value to convert:
(byte) Integer.parseInt("80", 16) & 0xFF
$3 ==> 128
That gets you a byte with the value you expect. Technically that result isn't correct and you must to switch the sign again, if you want to get an int or a hex string back again. I'd suggest you to don't use a byte array if you only want to convert between hex and dec.
A byte in Java stores numbers from -128 to 127. 80 in hex is 128 as an integer, which is too large to be stored in a byte. So, the value wraps around. Use a different type to store your value (such as a short).

Conversion from hex to binary keeping 8 bits in Java

I need to write in a 8x8 matrix the binary values of 8 hexadecimal numbers (one for row). Those numbers will be at the most 8 bits long. I wrote the following code to convert from hexadecimal to binary:
private String hexToBin (String hex){
int i = Integer.parseInt(hex, 16);
String bin = Integer.toBinaryString(i);
return bin;
}
But I have the problem that values below 0x80 don't need 8 bits to be represented in binary. My question is: is there a function to convert to binary in an 8-bit format (filling the left positions with zeros)? Thanks a lot
My question is: is there a function to convert to binary in an 8-bit format (filling the left positions with zeros)?
No, there isn't. You have to write it yourself.
Here's one simple way. If you know the input is always a single byte, then you could add 256 to the number before calling toBinaryString. That way, the string will be guaranteed to be 9 characters long, and then you can just shave off the first character using substring:
String bin = Integer.toBinaryString(256 + i).substring(1);
Hint: use string concatenation to add the appropriate number of zeros in the appropriate place.
For example:
public String hexToBin(String hex) throws NumberFormatException {
String bin = Integer.toBinaryString(Integer.parseInt(hex, 16));
int len = bin.length();
return len == 8 ? bin : "00000000".substring(len - 8) + bin;
}
(Warning: untested ...)
I've concatenated this way. Thanks!
private String hexToBin (String hex){
int i = Integer.parseInt(hex, 16);
String bin = Integer.toBinaryString(i);
while (bin.length()<8){
bin="0"+bin;
}
return bin;
}

Write bits in a file and retrieve them to a string of "0101.." in java?

I am working on a compression algorithm and for that i need to write strings of bits to a binary file and retrieve back exactly the same to a String again!
say, i have a string "10100100100....." and i will write them in a file as bits
(not chars '0' '1')
. and read back as bits and convert to string...
and this is for a large amount of data (>100 megabytes).
is there any neat and fast way of doing this?
So far i tried (and failed) writing them to bytes by sub-stringing into 8 bits and then as ASCII characters to a string and finally to a .txt file.
{
String Bits="10001010100000000000"; // a lot larger in actual program
String nCoded="";
char nextChar;
int i = 0;
for(i=0; i < Bits.length()-8; i += 8){
nextChar = (char)Integer.parseInt( Bits.substring(i, i+8), 2 );
nCoded += nextChar;
}
// for the remainding bits, padding
if(newBits.length()%8 != 0){
nCoded+=(char)Integer.parseInt(Bits.substring(i), 2);
}
nCoded+=(char)Bits.length()%8; //to track the remainder of Bits that was padded
writeToTextFile( nCoded, "file.txt"); //write the nCoded string to file
}
but this seems to corrupt information and inefficient.
again for clarification, i dont want the String to be written, its just a representation of the actual data. So, i want to
convert each 0 and 1 from the string representation to its binary form
and write that to file.
Here is a method you can use to convert the String to a series of bits, ready for output to file:
private byte[] toByteArray(String input){
//to charArray
char[] preBitChars = input.toCharArray();
int bitShortage = (8 - (preBitChars.length%8));
char[] bitChars = new char[preBitChars.length + bitShortage];
System.arraycopy(preBitChars, 0, bitChars, 0, preBitChars.length);
for (int i= 0; i < bitShortage; i++) {
bitChars[preBitChars.length + i]='0';
}
//to bytearray
byte[] byteArray = new byte[bitChars.length/8];
for(int i=0; i<bitChars.length; i++) {
if (bitChars[i]=='1'){
byteArray[byteArray.length - (i/8) - 1] |= 1<<(i%8);
}
}
return byteArray;
}
Passing the String "01010101" will return the result [85] as a byte[].
It turns out there is an easier way. There is a static Byte.parseByte(String) that returns Byte object. Calling:
Byte aByte = Byte.parseByte("01010101");
System.out.println(aByte);
Displays the same value: 85.
So you may ask a couple of questions here.
Why are we passing a String that is 8 characters in length. Well, you can prefix the String with an 9th character, that would represent a sign bit. I don't think you have this case, but if you needed to, the documentation for Byte.parseByte() states it should be:
An ASCII minus sign '-' ('\u002D') to indicate a negative value or an ASCII plus sign '+' ('\u002B') to indicate a positive value.
So from this information, you would need to break up your String manually into 8 bit Strings and call Byte.parseByte() to get a Byte object for each.
2) What about writing bits to a file? No, file writing is done in bytes. If you need to write the file, then read it back in and convert back to a String, you will need to reverse the process and read the file in as a byte[] then convert that to it's String representation.
A Hint on how to convert a byte to a nice String format can be found here:
Convert byte (java data type) value to bits (a string containing only 8 bits)
You can get an InputStream from a String, read each byte and write it to a file (byte is a smallest unit that you can read/write). Once everything is written, you can read the data in a similar way (i.e. InputStream) and use it. Below is an example:
String hugeSting = "10101010010101010110101001010101";
InputStream in = new ByteArrayInputStream(hugeSting.getBytes());
OutputStream out = new FileOutputStream("Test.txt");
byte b;
while((b = (byte) in.read()) != -1){
out.write(b);
}
in.close();
in = new FileInputStream("Test.txt");
//Read data

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 Byte.parseByte() error

I'm having a small error in my code that I can not for the life of me figure out.
I have an array of strings that are representations of binary data (after converting them from hex) for example:
one index is 1011 and another is 11100. I go through the array and pad each index with 0's so that each index is eight bytes. When I try to convert these representations into actual bytes I get an error when I try to parse '11111111' The error I get is:
java.lang.NumberFormatException: Value out of range. Value:"11111111" Radix:2
Here is a snippet:
String source = a.get("image block");
int val;
byte imageData[] = new byte[source.length()/2];
try {
f.createNewFile();
FileOutputStream output = new FileOutputStream(f);
for (int i=0; i<source.length(); i+=2) {
val = Integer.parseInt(source.substring(i, i+2), 16);
String temp = Integer.toBinaryString(val);
while (temp.length() != 8) {
temp = "0" + temp;
}
imageData[i/2] = Byte.parseByte(temp, 2);
}
Isn't the problem here that byte is a signed type, therefore its valid values are -128...127? If you parse it as an int (Using Integer.parseInt()), it should work.
By the way, you don't have to pad the number with zeroes either.
Once you parsed your binary string into an int, you can cast it to a byte, but the value will still be treated as signed, so binary 11111111 will become int 255 first, then byte -1 after the cast.
Well, eight one's is 255, and according to java.lang.Byte, the MAX_VALUE is 2^7 - 1 or positive 127.
So your code will fail because you number is too large. The first bit is reserved for the positive and negative sign.
according to parseByte
byte's only allow numbers in the range of -128 to 127. I would use an int instead, which holds numbers in the range of -2.1 billion to 2.1 billion.

Categories

Resources