Extracting data from binary data stream in nsdata
I'm new to objective c at the moment and trying to decode a data stream that I'm getting as an NSdata object..
the data is 8 bytes long, eg:
1 2 3 4
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+开发者_高级运维-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| code1 |code2 | code3 | code4 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5 6 7 8
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
code5 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
From the nsdata array, how could i easily put out the different codes, considering that code3 doesnt sit on a byte boundary?
I've tried the likes of this:
NSUInteger len = [data length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);
however cannot make it work properly with the different boundaries.. Apologies if this seems a bit vague, can confirm details if need be
What you're doing looks fine - what's the issue? Are you able to get the data in to your byteData pointer? If so, then it's no different between objective-c or C or anything else (and NSData isn't really a good tag then) - you just need to access your bytes bitwise.
This could be achieved by creating a structure with bitfield definitions like this (pseudocode, google bitfield)
struct
{
char byte1;
char a3bitfield : 3;
char a5bitfield : 5;
char byte3;
}
Or by using bitmasks and or by using shifts.
Edit in response to comment:
This shows how to do the shifting
First issue you're going to have is that you are showing your bits from left to right, which on little-endian systems is not accurate, you need to think about the bits as being:
7 6 5 4 3 2 1 0
Instead of
0 1 2 3 4 5 6 7
Otherwise you will never understand how the masking and shifting directions will work.
So assuming that you have bytes broken out, as you seem to, and you know what byte you're operating on, byte x :
7 6 5 4 3 2 1 0 [5 bits a][3 bits b]
Where a and b are messages you care about, the way to get these "alone" would be:
char onlya = ((x & 11111000b) >> 3);
Which means, I want tto use those top 5 bits of a, and discard the lowest 3 bits, and then shift everything 3 bits to the right to compensate. If you started with: AAAAABBB where A is data from a and B is data from B that you don't care about, the "x & 11111000b" will result in: AAAAA000 And the subsequent >> 3 will result in: 000AAAAA
Where the A's come from right shifting, introducing 0's where the gaps were and discarding the 0's on the right.
So to get B alone in this case, you'd only have to do:
char onlyb = (x & 00000111b);
No shift necessary.
If you're working across bit boundaries with 2 bytes N and M such as:
N M 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 X X X X A A A A A A A X X X X X
You would do:
char merged = 0;
merged |= (N & 00001111b) << 3;
merged |= (M & 11100000b) >> 5;
I'm masking out to only get A from N and M, and then I'm shifting to the RESULTING LOCATION. So that when I'm done with these 3 steps in order, the result on merged will be:
merged = 0 gives: 0 0 0 0 0 0 0 0
First merged |= gives: 0 N N N N 0 0 0
Second merged |= gives: 0 N N N N M M M
At this point, you act on your data as you normally would (cast to int or whatever)
And like I said, the alternative is bitfields
精彩评论