Hi all,
not really new to Java nor binary format (as a beginner), but I do need some help regarding bit masking and shifting.
First of all I will explain my problem, and the approach that I think is the best.
I prefer a good explanation rather than code-dump ;)
The Problem
I'm reading the first 5 bytes from a binary file. (For now, just to keep it simple)
byte binaryData[] = new byte[5];
dis.read(binaryData); //dis is a DataInputStream object
Those 5 bytes, representing 40 bits, are structured as follow
(actually they are structured in words of 12bits, but since a byte has 8bits, this is how I depict it)
X - don't care
A - bits representing valueA (6-bit value, from 0 up to 63)
B - bits representing valueB (6-bit value, from 0 up to 63)
C - bits representing valueC (5-bit value, from 0 up to 31)
| - 8 bit separator
*XXXXXXXX | XXXX{color:#339966}AAAA{color} | {color:#339966}AA{color}{color:#ffcc00}BBBBBB{color} | XXXXXXX{color:#ff0000}C{color} | {color:#ff0000}CCCC{color}XXXX*
An approach
1) read valueC is...
a) shift binaryData >> 4, such as *XXXXXXXX | XXXXXXXX | {color:#339966}AAAAAA{color}{color:#ff9900}BB{color} | {color:#ff9900}BBBB{color}XXXX| XXX{color:#ff0000}CCCCC{color}*
b) set bits 5, 6 and 7 to 0, such as binaryData[4] = 000CCCCC
c) convert binaryData[4] to int
2) read valueA is...
a) shift binaryData >> 2 and obtain binaryData[2] = XXAAAAAA
b) set bits 6 and 7 to 0 and obtain 00AAAAAA
c) convert binaryData[2] to int
3) Read valueB (binaryData[3] is set as BBBBBBXX, from step 2 ) is...
a) shift binaryData[3] > 2 and obtain XXBBBBBB
b) Set bit 6 and 7 to 0 from binaryData[3], such as binaryData[3] = 00BBBBBB
c) Convert binaryData[3] to int.
First of all, do you think this is the best (i.e., optimized/eficient) approach?
Regarding the proposed approach, I need some explanation:
*~ How do I shift X bits to right from a byte array?*
As I have read
int a;
a = 16;
a = a >> 1; // a = 8
byte aByte = (byte) 0xf0; // 11110000
aByte = (byte) (aByte >> 1); // 0111 1000
would be enough.
But, how do I shift byte array? (byte[])
Would be masks a solution?
Here appears another problem. I've seen some magic numbers to use as mask, but i really want to understand those masks.
Once the bit-shift done, (needed for 1a, 2a and 3a) would be the following masks appropriate?
maskForValueC = 31
maskForValueAandB = 63
31d = 0001 1111b (to extract 000CCCCC)
632d = 0011 1111b (to extract 00AAAAAA and 00BBBBBB)
Finally, only converting byte to int is left to be done.
...// binaryData>> 4
int valueC = (int) binaryData[4] & maskForValueC;
...// binaryData>> 2
int valueA = (int) binaryData[2] & maskForValueAandB
...// binaryData>> 2
int valueB = (int) binaryData[3] & maskForValueAandB
Is that rigth?
I've read the BitSet documentation, but i think that it is helpful only when dealing with > 64 bits words.
I might need in the future but for now i do not want to un-focus from this problem.
I've also read some documentation and related topic in [1|http://mindprod.com/jgloss/masking.html], [2|http://mindprod.com/jgloss/binary.html], [3|http://www.velocityreviews.com/forums/t135054-p-can-java-read-bits.html], ...
I appreciate your time and help ;)