I am receiving data from a hardware device. I receive it as an array of bytes. I want to build and store a String that can show me the data of the array of bytes. This is what I have:
byte[] buffer = new byte[BUFFER_SIZE];
bytes = mmInStream.read(buffer);
String[] str = new String[bytes];
StringBuffer readMessage = new StringBuffer();
for(int i=0; i<bytes; ++i){
str[i] = Integer.toHexString(buffer[i]);
while (str[i].length() < 8){ //standarize size
str[i] = '0' + str[i];
}
readMessage.append(str[i]);
}
The main problem that I have is that I am receiving unexpected bytes when I transform the bytes to String. I am receiving pure bytes so I am expecting the values to range from 0x00 to 0xFF. However, some of the bytes are transformed to bytes like 0xFFFFFF09. Why is this happening??
You should convert byte to int this way:
int byteAsInt = ((int)buffer[i]) & 0x000000FF;
str[i] = Integer.toHexString(byteAsInt);
byte is a signed data type, so 0xFF is -1. When converting to a larger integral type it will still be -1, i.e. 0xFFFF or 0xFFFFFFFF for 16 and 32 bit integer values.
Edit:
If you want to get the unsigned value, do a bitwise AND (&) with 0xFF when assigning to a larger variable.
Without running your code I suppose that your problem is in your inner loop.
while (str[i].length() < 8){ //standarize size
str[i] = '0' + str[i];
}
What would you like to achieve? Print 0xFF instead of FF? In this case just modify one line as following:
str[i] = "0x" + Integer.toHexString(buffer[i]);
and remove the inner loop.
Related
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
I'm writing a little program in android and in it I've a list of byte values in a string variable. something like this :
String src = "255216173005050";
Now, what i need to do is to extract the byte values from the source string and store them in a byte variables. (in above source string, i'll have 5 bytes to store)
For doing this i could successfully read source string and separate the byte values by 3 characters. (255, 216, 173, 005, 050)
The problem is that i failed to convert these strings to their byte values.
it is what I've already done :
String str = "255";
byte b = (byte) Integer.parseInt(str);
By running this, b will be -60 !
Is there
Please help me !
When you write
byte b = (byte) Integer.parseInt(str);
you will get a signed byte. If you look at your int that is discarded using something like
int i = Integer.parseInt(str);
System.out.println(i);
byte b = (byte) i;
you will probably see that i contains the value you want.
This should work. Then just access various indices of the byte array to get the individual pieces. If your text is an abnormal character set - then pass the character set into the getBytes() method.
byte[] bytes = src.getBytes();
Don't use parseInt when you want a byte; instead try Byte.parseByte. Also note that bytes have a range of -128 to 127 (inclusive).
I have a String array, each array element is a hex string that consist of 2 chars.
For example the array could be:
String a = {"aa","ff","00",.....}
How can I convert this array of strings to an array of bytes in Java?
If you want to parse unsigned byte hex-strings, use
byte[] b = new byte[a.length()];
for (int i=0; i<a.length(); i++) {
b[i] = (byte) Short.parseShort(a[i], 16);
}
"ff" will be parsed to -1, as per two's compliment.
If you want "ff" to parse to 255 (higher than a java byte can hold) you will need to use shorts
short[] b = new short[a.length()];
for (int i=0; i<a.length(); i++) {
b[i] = Short.parseShort(a[i], 16);
}
Loop through the array, and convert each String to a byte using
byte b = (byte) (Integer.parseInt(theHexaString, 16));
Byte.parseByte() parses signed bytes only, and doesn't consider the sign bit as a sign bit.
If I understand correctly, you need the byte representation of the concatenated strings? Something like:
public byte[] getBytes(String[] array) {
StringBuilder builder = new StringBuilder();
for(String s: array) {
builder.append(s);
}
return builder.toString().getBytes();
}
You should take a look at the ByteArrayOutputStream.
You can then iterate through each string you have and use the Byte.parseByte() method. You can than add it to the ByteArrayOutputStream by using the write method.
Once you will have converted all the Strings, you can use the ByteArrayOutputStream's toByteArray() method.
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.
I'm working with java.
I have a byte array (8 bits in each position of the array) and what I need to do is to put together 2 of the values of the array and get a value.
I'll try to explain myself better; I'm extracting audio data from a audio file. This data is stored in a byte array. Each audio sample has a size of 16 bits. If the array is:
byte[] audioData;
What I need is to get 1 value from samples audioData[0] and audioData[1] in order to get 1 audio sample.
Can anyone explain me how to do this?
Thanks in advance.
I'm not a Java developer so this could be completely off-base, but have you considered using a ByteBuffer?
Assume the LSB is at data[0]
int val;
val = (((int)data[0]) & 0x00FF) | ((int)data[1]<<8);
As suggested before, Java has classes to help you with this. You can wrap your array with a ByteBuffer and then get an IntBuffer view of it.
ByteBuffer bb = ByteBuffer.wrap(audioData);
// optional: bb.order(ByteOrder.BIG_ENDIAN) or bb.order(ByteOrder.LITTLE_ENDIAN)
IntBuffer ib = bb.asIntBuffer();
int firstInt = ib.get(0);
ByteInputStream b = new ByteInputStream(audioData);
DataInputStream data = new DataInputStream(b);
short value = data.readShort();
The advantage of the above code is that you can keep reading the rest of 'data' in the same way.
A simpler solution for just two values might be:
short value = (short) ((audioData[0]<<8) | (audioData[1] & 0xff));
This simple solution extracts two bytes, and pieces them together with the first byte being the higher order bits and the second byte the lower order bits (this is known as Big-Endian; if your byte array contained Little-Endian data, you would shift the second byte over instead for 16-bit numbers; for Little-Endian 32-bit numbers, you would have to reverse the order of all 4 bytes, because Java's integers follow Big-Endian ordering).
easier way in Java to parse an array of bytes to bits is JBBP usage
class Parsed { #Bin(type = BinType.BIT_ARRAY) byte [] bits;}
final Parsed parsed = JBBPParser.prepare("bit:1 [_] bits;").parse(theByteArray).mapTo(Parsed.class);
the code will place parsed bits of each byte as 8 bytes in the bits array of the Parsed class instance
You can convert to a short (2 bytes) by logical or-ing the two bytes together:
short value = ((short) audioData[0]) | ((short) audioData[1] << 8);
I suggest you take a look at Preon. In Preon, you would be able to say something like this:
class Sample {
#BoundNumber(size="16") // Size of the sample in bits
int value;
}
class AudioFile {
#BoundList(size="...") // Number of samples
Sample[] samples;
}
byte[] buffer = ...;
Codec<AudioFile> codec = Codecs.create(AudioFile.class);
AudioFile audioFile = codec.decode(buffer);
You can do it like this, no libraries or external classes.
byte myByte = (byte) -128;
for(int i = 0 ; i < 8 ; i++) {
boolean val = (myByte & 256) > 0;
myByte = (byte) (myByte << 1);
System.out.print(val ? 1 : 0);
}
System.out.println();
byte myByte = 0x5B;
boolean bits = new boolean[8];
for(int i = 0 ; i < 8 ; i++)
bit[i] = (myByte%2 == 1);
The results is an array of zeros and ones where 1=TRUE and 0=FALSE :)