I have one array of bytes. I want to access each of the bytes and want its equivalent binary value(of 8 bits) so as to carry out next operations on it. I've heard of BitSet but is there any other way of dealing with this?
Thank you.
If you just need the String representation of it in binary you can simply use Integer.toString() with the optional second parameter set to 2 for binary.
To perform general bit twiddling on any integral type, you have to use logical and bitshift operators.
// tests if bit is set in value
boolean isSet(byte value, int bit){
return (value&(1<<bit))!=0;
}
// returns a byte with the required bit set
byte set(byte value, int bit){
return value|(1<<bit);
}
You might find something along the lines of what you're looking in the Guava Primitives package.
Alternatively, you might want to write something like
public boolean[] convert(byte...bs) {
boolean[] result = new boolean[Byte.SIZE*bs.length];
int offset = 0;
for (byte b : bs) {
for (int i=0; i<Byte.SIZE; i++) result[i+offset] = (b >> i & 0x1) != 0x0;
offset+=Byte.SIZE;
}
return result;
}
That's not tested, but the idea is there. There are also easy modifications to the loops/assignment to return an array of something else (say, int or long).
BitSet.valueOf(byte[] bytes)
You may have to take a look at the source code how it's implemented if you are not using java 7
Java has bitwise operators. See a tutorial example.
The Java programming language also provides operators that perform bitwise and bit shift operations on integral types. The operators discussed in this section are less commonly used. Therefore, their coverage is brief; the intent is to simply make you aware that these operators exist.
The unary bitwise complement operator "~" inverts a bit pattern; it can be applied to any of the integral types, making every "0" a "1" and every "1" a "0". For example, a byte contains 8 bits; applying this operator to a value whose bit pattern is "00000000" would change its pattern to "11111111".
A byte value IS integral, you can check bit state using masking operations.
The least significant bit corresponds to the mask 1 or 0x1, the next bit correspond to 0x2, etc.
byte b = 3;
if((b & 0x1) == 0x1) {
// LSB is on
} else {
// LSB is off
}
byte ar[] ;
byte b = ar[0];//you have 8 bits value here,if I understood your Question correctly :)
Well I think I get what you mean. Now a rather substantial error with this is that it doesn't work on negative numbers. However assuming you're not using it to read file inputs, you might still be able to use it.
public static ArrayList<Boolean> toBitArr(byte[] bytearr){
ArrayList<Boolean> bitarr = new ArrayList<Boolean>();
ArrayList<Boolean> temp = new ArrayList<Boolean>();
int i = 0;
for(byte b: bytearr){
while(Math.abs(b) > 0){
temp.add((b % 2) == 1);
b = (byte) (b >> 1);
}
Collections.reverse(temp);
bitarr.addAll(temp);
temp.clear();
}
return bitarr;
}
Here is a sample, I hope it is useful for you!
DatagramSocket socket = new DatagramSocket(6160, InetAddress.getByName("0.0.0.0"));
socket.setBroadcast(true);
while (true) {
byte[] recvBuf = new byte[26];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(packet);
String bitArray = toBitArray(recvBuf);
System.out.println(Integer.parseInt(bitArray.substring(0, 8), 2)); // convert first byte binary to decimal
System.out.println(Integer.parseInt(bitArray.substring(8, 16), 2)); // convert second byte binary to decimal
}
public static String toBitArray(byte[] byteArray) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteArray.length; i++) {
sb.append(String.format("%8s", Integer.toBinaryString(byteArray[i] & 0xFF)).replace(' ', '0'));
}
return sb.toString();
}
Related
If I had a byte instead of an integer, I could easily create a boolean array with 256 positions and check:
boolean[] allBytes = new boolean[256];
if (allBytes[value & 0xFF] == true) {
// ...
}
Because I have an integer, I can't have an array with size 2 billion. What is the fastest way to check if an integer is true or false? A set of Integers? A hashtable?
EDIT1: I want to associate for every possible integer (2 billion) a true or false flag.
EDIT2: I have ID X (integer) and I need a quick way to know if ID X is ON or OFF.
A BitSet can't handle negative numbers. But there's a simple way around:
class BigBitSet {
private final BitSet[] bitSets = new BitSet[] {new BitSet(), new BitSet()};
public boolean get(int bitIndex) {
return bitIndex < 0 ? bitSets[1].get(~bitIndex)
: bitSets[0].get(bitIndex);
}
...
}
The second BitSet is for negative numbers, which get translated via the '~' operator (that's better than simply negating as it works for Integer.MIN_VALUE, too).
The memory consumption may get up to 4 Gib, i.e., about 524 MB.
I feel stupid for even elaborating on this.
The smallest unit of information your computer can store is a bit, right? A bit has two states, you want two states, so lets just say bit=0 is false and bit=1 is true.
So you need as many bits as there are possible int's, 2^32 = 4,294,967,296. You can fit 8 bits into a byte, so you need only 2^32 / 8 = 536,870,912 bytes.
From that easily follows code to address each of these bits in the bytes...
byte[] store = new byte[1 << 29]; // 2^29 bytes provide 2^32 bits
void setBit(int i) {
int byteIndex = i >>> 3;
int bitMask = 1 << (i & 7);
store[byteIndex] |= bitMask;
}
boolean testBit(int i) {
int byteIndex = i >>> 3;
int bitMask = 1 << (i & 7);
return (store[byteIndex] & bitMask) != 0;
}
java.util.BitSet provides practically the same premade in a nice class, only you can use it to store a maximum of 2^31 bits since it does not work with negative bit indices.
Since you're using Java, use BitSet. It's fast and easy. If you prefer, you could also use an array of primitive longs or BigInteger, but this is really what BitSet is for.
http://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html
I received a CRC function written in C from a hardware partner. Messages send by his devices are signed using this code. Can anyone help me to translate it to Java?
int8 crc8(int8*buf, int8 data_byte)
{
int8 crc=0x00;
int8 data_bit=0x80;
while(data_byte>0)
{
if(((crc&0x01)!=0)!=((buf[data_byte]&data_bit)!=0))
{
crc>>=1;
crc^=0xCD;
}
else
crc>>=1;
data_bit>>=1;
if(!data_bit)
{
data_bit=0x80;
data_byte--;
}
}
return(crc);
}
I tried to convert this to Java, but the result is not I expect.
public static byte crc8(byte [] buf, byte data_byte)
{
byte crc = 0x00;
byte data_bit = (byte)0x80;
while(data_byte>0)
{
if(((crc&0x01)!=0)!=((buf[data_byte]&data_bit)!=0))
{
crc>>=1;
crc^=0xCD;
}
else
{
crc>>=1;
}
data_bit>>=1;
if(data_bit == 0)
{
data_bit= (byte)0x80;
data_byte--;
}
}
return crc;
}
I suppose that this is the error: if(data_bit != 0)
EDIT:
I changed the code to byte in my conversion method. I receive my data from a socket and convert this then to a String where I get a byteArray out from.
An input example is 16, 0, 1, -15, 43, 6, 1, 6, 8, 0, 111, 0, 0 ,49
where the last field (49) should be the checksum
I also tried Durandals version, but my result is still not valid.
This is how I read the data
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
char[] buffer = new char[14];
int count= bufferedReader.read(buffer, 0, 14);
String msg = new String(buffer, 0, count);
byte[] content = msg.getBytes();
if(!data_bit)
translates to
if(data_bit == 0)
You really need to use bytes and not shorts. To get around the problem you had using bytes, use this
byte data_bit = (byte)0x80;
Also, as Mark says, you need to use >>> instead of >>.
Translate the code 1:1, paying extra attention to all operations done on bytes to account for java's implicit cast to int (e.g. (byte >>> 1) is absolutely worthless because the byte is first extendet to int, shifted and then cast back, making it effectively a signed shift no matter what).
Therefore local variables are best declared as int and when loaded from a bytearray masked to yield unsigned extension: int x = byte[i] & 0xFF; Since in the only place that is done data is already masked down to a single bit (in the if) there is nothing special to be done.
Applying to the C code yields:
int crc8(byte[] buf, int dataCount) {
int crc = 0;
int data_bit = 0x80;
while(dataCount > 0) {
if ( ((crc & 0x01)!=0) != ((buf[dataCount] & data_bit)!=0)) {
crc >>= 1;
crc ^= 0xCD;
} else {
crc >>= 1;
}
data_bit >>= 1;
if (data_bit == 0) {
data_bit = 0x80;
dataCount--;
}
}
return crc;
}
That said, the code isn't very efficient (it processes input bit by bit, there are faster implementations processing entire bytes, using a table for each possible byte added, but you probably don't care for this use case).
Also, beware when you compare the crc from this method to a byte, you must mask the byte properly with 0xFF, otherwise comparison will fail for values >=0x80:
(int) crc == (byte) crc & 0xFF
EDIT:
What worries my even about the original code, that data_byte is clearly intended to specify a length, first it calculates in reverse order and also, it will access an additional byte after the specfied number (data_byte is not decremented before the loop). I suspect the original is (already) broken code, or the calls to it are very messy.
I'm trying to represent the port number 9876 (or 0x2694 in hex) in a two byte array:
class foo {
public static void main (String args[]) {
byte[] sendData = new byte[1];
sendData[0] = 0x26;
sendData[1] = 0x94;
}
}
But I get a warning about possible loss of precision:
foo.java:5: possible loss of precision
found : int
required: byte
sendData[1] = 0x94;
^
1 error
How can I represent the number 9876 in a two byte array without losing precision?
NOTE: I selected the code by #Björn as the correct answer, but the code by #glowcoder also works well. It's just a different approach to the same problem. Thank you all!
Have you tried casting to a byte ? e.g.
sendData[1] = (byte)0x94;
0x94 is 148 in decimal, which exceeds the range of byte in java (-128 to 127).
You can do one of the following:
1) A cast will work fine because it will preserve the binary representation (no meaningful bits are truncated for 0x00 to 0xFF):
sendData[1] = (byte)0x94;
2) The binary representation of 0x94 as a signed byte is -108 (-0x6C), so the following will have the same effect:
sendData[1] = -0x6C; //or -108 in decimal
Björn gave a good generic answer with using streams. You can also do this same thing using java.nio.ByteBuffer which results in slightly less code and you could also control endianess (byte order) of the output.
To create the byte array:
public static byte[] toByteArray(int bits) {
ByteBuffer buf = ByteBuffer.allocate(4);
buf.putInt(bits);
return buf.array();
}
To reverse it:
public static int fromByteArray(byte[] b) {
ByteBuffer buf = ByteBuffer.wrap(b);
return buf.getInt();
}
My first answer would be bitshifting, but on a second thought I think using outputstreams could be better and more simple to understand. I usually avoid casting, but if you're not going for a generic solution I guess that would be okay. :)
Using streams, a generic solution:
public byte[] intToByteArray(final int i) throws java.io.IOException {
java.io.ByteArrayOutputStream b = new java.io.ByteArrayOutputStream();
java.io.DataOutputStream d = new java.io.DataOutputStream(b);
d.writeInt(i);
d.flush();
return b.toByteArray();
}
And to reverse it:
public int byteArrayToInt(final byte[] b) throws IOException {
java.io.ByteArrayInputStream ba = new java.io.ByteArrayInputStream(b);
java.io.DataInputStream d = new java.io.DataInputStream(ba);
return d.readInt();
}
You have to cast to (byte) as default number type in java is int, which is bigger than byte. As long as the value fits in byte it is ok to cast.
Try this:
sendData[0] =(byte)0x26
sendData[1] =(byte)0x94
Or this:
sendData[0] =(byte)38
sendData[1] =(byte)148
You must cast data into byte in order to assign it to a byte!
That does not mean you lost precision, just writing 0x26 means an int to Java compiler..
But also note: range of a byte is from -128 to 127, so in case of 0x94=148 it will be represented after byte casting as '-108' , so it will not work correctly in mathematical computations..
It's because everything in Java is signed. 0x94 (148) is greater than Byte.MAX_VALUE(2^7-1).
What you need is
public static byte[] intToByteArray(int value) {
byte[] b = new byte[4];
for (int i = 0; i < 4; i++) {
int offset = (b.length - 1 - i) * 8;
b[i] = (byte) ((value >>> offset) & 0xFF);
}
return b;
}
I need to convert a byte into an array of 4 booleans in Java. How might I go about this?
Per Michael Petrotta's comment to your question, you need to decide which bits in the 8-bit byte should be tested for the resulting boolean array. For demonstration purposes, let's assume you want the four rightmost bits, then something like this should work:
public static boolean[] booleanArrayFromByte(byte x) {
boolean bs[] = new boolean[4];
bs[0] = ((x & 0x01) != 0);
bs[1] = ((x & 0x02) != 0);
bs[2] = ((x & 0x04) != 0);
bs[3] = ((x & 0x08) != 0);
return bs;
}
The hexadecimal values (0x01, 0x02, etc.) in this example are special bit masks that have only a single bit set at the desired location; so 0x01 has only the rightmost bit set, 0x08 has only the fourth-from-right bit set. By testing the given byte against these values with the bitwise AND operator (&) you will get that value back if the bit is set, or zero if not. If you want to check different bits, other than the rightmost four, then you'll have to create different bitmasks.
On specification
Others are raising a very valid point: in Java, Byte.SIZE == 8. That is, there are 8 bits in a byte. You need to define how you want to map 8 bits into 4 boolean values; otherwise we can only guess what is it you're trying to do.
On BitSet
Regardless of how you do this mapping, however, it's unlikely that boolean[] really is the best representation. A java.util.BitSet may be better. Here's an example:
import java.util.*;
public class BitSetExample {
static BitSet toBitSet(byte b) {
BitSet bs = new BitSet(Byte.SIZE);
for (int i = 0; i < Byte.SIZE; i++) {
if (((b >> i) & 1) == 1) {
bs.set(i);
}
}
return bs;
}
public static void main(String[] args) {
BitSet bs = toBitSet((byte) 10);
System.out.println(bs); // prints "{1, 3}"
System.out.println(bs.get(3)); // prints "true"
System.out.println(bs.get(2)); // prints "false"
byte b = 25;
System.out.println(toBitSet(b)); // prints "{0, 3, 4}"
bs.or(toBitSet(b));
System.out.println(bs); // prints "{0, 1, 3, 4}"
}
}
The above code uses the standard bit probing technique to convert a byte to a BitSet. Note that a (byte) 10 has its bits 1 and 3 set (i.e. 10 = 2^1 + 2^3 where ^ denotes exponentiation).
The example also shows how to perform an or/set union operation on BitSet.
On EnumSet
Possibly another applicable data structure is an EnumSet, which is a Set implementation highly optimized for enum. Here's an example:
import java.util.*;
public class EnumSetExample {
enum Style {
BOLD, ITALIC, UNDERLINE, BLINKING;
}
public static void main(String[] args) {
EnumSet<Style> myStyle = EnumSet.of(Style.BOLD, Style.UNDERLINE);
System.out.println(myStyle);
// prints "[BOLD, UNDERLINE]"
System.out.println(myStyle.contains(Style.UNDERLINE));
// prints "true"
System.out.println(myStyle.contains(Style.BLINKING));
// prints "false" (thank goodness!)
myStyle.add(Style.ITALIC);
System.out.println(myStyle);
// prints "[BOLD, ITALIC, UNDERLINE]"
}
}
See also
Effective Java 2nd Edition, Item 32: Use EnumSet instead of bit fields
As an addendum to maerics' answer, this is how you could convert the bool array back into a byte, if needed :
public static byte byteFromBooleanArray(bool[] _boolArray)
{
byte x = 0;
x += _boolArray[0] ? (byte)1 : (byte)0;
x += _boolArray[1] ? (byte)2 : (byte)0;
x += _boolArray[2] ? (byte)4 : (byte)0;
x += _boolArray[3] ? (byte)8 : (byte)0;
return x;
}
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 :)