I need to wrap a string into a sequence of bytes according to a pattern:
First byte should be 0x02
The second byte and the third byte should be the length of the string in bytes
Then the string sequence of bytes should come
Next byte should be 0x03
Last byte should be the logical XOR of the bytes sequence of the string
This is what I tried to do:
- (NSData *)sendMessage:(NSData *)message {
Byte stx = 0x02;
Byte etx = 0x03;
Byte length = [message length];
// Computes bitwise XOR of message bytes
const char *bytes = [message bytes];
Byte crc = bytes[0];
for (int i = 1; i < [message length]; i++)
crc = crc ^ bytes[i];
NSString *packet = [NSString stringWithFormat:#"%x%x%s%x%x", stx, (uint16_t)length, bytes, etx, crc];
return [packet dataUsingEncoding:NSUTF8Encoding];
}
I need to write this bytes sequence into a CBCharacteristic that gets then read by a BT device, checks the format and, if it's correct, display the string. Anyway, it keeps rejecting it. Could someone please explain me where do I fail?
The problem is the use of stringWithFormat to build the data. That string and its resulting UTF-8 encoding is not at all what you need.
Use NSMutableData to add the bytes:
NSMutableData *result = [[NSMutableData alloc] init];
[result appendBytes:&stx length:1];
uint16_t len = (uint16_t)length;
[result appendBytes:&len length:2]; // might have a byte ordering issue here
[result appendData:message];
[result appendBytes:&crc length:1];
Related
I'm needing to get all of the bytes from an NSData object after the 12th index.
So far I have
const char* fileBytes = (const char*)[imageData bytes];
NSUInteger length = [imageData length];
NSUInteger index;
NSMutableString *byteString = [[NSMutableString alloc] init];
[SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:#"bytes: %#", imageData.description]];
for (index = 12; index<length; index++) { //Grabba returns a 12 byte header.
char aByte = fileBytes[index];
[byteString appendString:[NSString stringWithFormat:#"%x", aByte]];
}
But what I'd really like to do is create a const char* and just append each byte at index 12 till the end to it. How can I append bytes to a series of bytes?
What you need to do is use some standard C library calls. You know how many bytes there are in the NSData object, so you can alloc the storage you need and then memcpy all the bytes from the 12th one on.
NSUInteger length = [data length];
char* theBytes = malloc(sizeof(char)*(length-11));
memcpy(theBytes,fileBytes+11,length-11);
theBytes cannot be a const char* because of course it is not constant until after you have called memcpy.
Remember to call free when you are done with the string.
I have a ASCII file which I want to read byte by byte into a Byte buffer. I am clueless and confused between many aspects. Can anyone guide me with the correct way to do it?
Any help is appreciated.
I finaly got the answer here. So what I did is,
NSMutableString *bundlePath = [NSMutableString stringWithString:
[[NSBundle mainBundle]pathForResource:#"excercise1" ofType:nil]];
NSData *myData = [NSData dataWithContentsOfFile:bundlePath];
uint8_t * bytePtr = (uint8_t * )[myData bytes];
NSInteger totalData = [myData length] / sizeof(uint8_t);
NSLog(#"Data byte chunk: ");
for (int i = 0 ; i < totalData; i ++)
{
NSLog(#" %x", bytePtr[i]);
}
and it worked as I wanted it to be. I got the bytes in an array.
I'm using this code to create hash from giving string to devolving IOS App.
-(NSString*) sha1:(NSString*)input
{
const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:input.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}
my PHP code is
sha1(json_encode($array));
I have string that contain Arabic languages.
when I create hash from English string and compare it with hash created from php code under Ubuntu*strong text* the result will be the same.
but when I create the hash with Arabic character it will and compare it with hash created from php code does't mach the result.
so what is the man problem with this code.
Thanks
input.length is the number of characters, not the number of bytes, the difference is that many bytes under UTF8 encoding are multiple bytes in length.
Replace:
const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:input.length];
with the NSString method:
NSData *data = [input dataUsingEncoding: NSUTF8StringEncoding];
There is no need for the intermediate const char *cstr.
I found my problem that come from my PHP json_encode($array) function.
so I found this function in http://php.net/manual/en/function.json-encode.php that encode my json with UTF-8 character
function my_json_encode($arr)
{
//convmap since 0x80 char codes so it takes all multibyte codes (above ASCII 127). So such characters are being "hidden" from normal json_encoding
array_walk_recursive($arr, function (&$item, $key) { if (is_string($item)) $item = mb_encode_numericentity($item, array (0x80, 0xffff, 0, 0xffff), 'UTF-8'); });
return mb_decode_numericentity(json_encode($arr), array (0x80, 0xffff, 0, 0xffff), 'UTF-8');
}
EX:
sha1(my_json_encode($newArray)
I need somewhere to save and then to retrieve Sint16 (2 bytes).
I get:
SInt16* frames = (SInt16*)inBuffer->mAudioData;
and want to save &frames[i] somewhere (NSMutableData?) that could later easily retrieve. I tried to save like this (in cycle):
[recordedData appendBytes:&frames[i] length:1];
and retrieve:
SInt16* framesRetrieve ;
//sets up mybytes buffer and reads in data from myData
framesRetrieve = (SInt16*)malloc([mutableData framesRetrieve]);
[mutableData getBytes:framesRetrieve];
But this return not the same as i put into.
So what could be a solution ?
thanks.
You need to know the length of the data and then you can store the whole buffer in an NSMutableData object:
To store:
SInt16 *frames = ...;
NSUInteger length = ...; // Assuming number of elements in frames, not bytes!
NSMutableData *data = [[NSMutableData alloc] initWithCapacity:0];
[data appendBytes:(const void *)frames length:length * sizeof(SInt16)];
To retrieve:
SInt16 *frames = (SInt16 *)[data bytes];
NSUInteger length = [data length] / sizeof(SInt16);
You are only copying one byte from a 2 byte variable. Try appending both bytes to the NSMutableData at once.
[recordedData appendBytes: frames length:sizeof(SInt16)];
ex:
NSData *data = [NSData dataWithContentsOfFile:filePath];
int len = [data length];
if len = 10000,
i hope i can convert 1000 to a NSData look like
char hoperesult[] = {0x10, 0x27, 0x00, 0x00}
and hoperesult[] must always 4 Bytes
So you want the length in 4 little-endian bytes, correct? I think this will do it:
unsigned int len = [data length];
uint32_t little = (uint32_t)NSSwapHostIntToLittle(len);
NSData *byteData = [NSData dataWithBytes:&little length:4];
(Note that most network protocols use big-endian, but you showed little-endian so that's what this does.)
I'm not 100% sure what you mean here, but I think you are attempting to fill hoperesult with the values found in the file at 'filePath'.
struct _hoperesult {
char data[4];
} *hoperesult;
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSUInteger len = [data length];
NSRange offset;
offset.location = 0;
offset.length = sizeof(_hoperesult);
NSData *hoperesultData;
while( (offset.location + offset.length) < len ) {
hoperesultData = [data subdataWithRange:offset];
// the equivalent of your char hoperesult[] content...
hoperesult = [hoperesultData bytes]
}
An instance of NSData can return a pointer to the actual bytes of data using the "bytes" method. It returns a (const void *). You could in theory simply cast [data bytes] to a char * and use the offset directly; or you can do like in the above code and return smaller chucks of NSData.
Hope that helps!