How to create byte array from NSData - iphone

Please any one guide me how to create bytes array from nsdata here is my code for createing nsdata
NSData* data = UIImagePNGRepresentation(img);

If you only want to read them, there's a really easy method :
unsigned char *bytes = [data bytes];
If you want to edit the data, there's a method on NSData that does this.
// Make your array to hold the bytes
NSUInteger length = [data length];
unsigned char *bytes = malloc( length * sizeof(unsigned char) );
// Get the data
[data getBytes:bytes length:length];
NB Don't forget - if you're copying the data, you also have to call free(bytes) at some point ;)

Here is fastest way (but pretty danger) to get array:
unsigned char *bytesArray = data.bytes;
NSUInteger lengthOfBytesArray = data.length;
before trying to get byte#100 you should check lengthOfBytesArray like:
if (lengthOfBytesArray > 100 + 1)
{
unsigned char byteWithOffset100 = bytesArray[100];
}
And another safe and more objc-like way:
- (NSArray*) arrayOfBytesFromData:(NSData*) data
{
if (data.length > 0)
{
NSMutableArray *array = [NSMutableArray arrayWithCapacity:data.length];
NSUInteger i = 0;
for (i = 0; i < data.length; i++)
{
unsigned char byteFromArray = data.bytes[i];
[array addObject:[NSValue valueWithBytes:&byteFromArray
objCType:#encode(unsigned char)]];
}
return [NSArray arrayWithArray:array];
}
return nil;
}

Related

blowfish algorithm objective c

I have to use Blowfish algorithm in my code for encryption and decryption. After calling the decryption method, blowfishDecrypt, I am getting the value in NSData but it give me always null when I convert it to NSString.
I am using the following code :
-(void)methodCalled
{
syncTime=#"c7c937169084b20c3ff882dcda193a59";
NSData* data = [syncTime dataUsingEncoding:NSUTF8StringEncoding];
NSData* data2 = [#"R=U!LH$O2B#" dataUsingEncoding:NSUTF8StringEncoding];
NSData* dycryptData=[self blowfishDecrypt:data usingKey:data2];
// prints <0eec37b6 2b76c2df cdf72356 0f033ed8 d6bd37dd 5223bf66 5c318ebe 07f3cf71>
NSLog(#"%#",dycryptData);
NSString *dSync=[[NSString alloc] initWithBytes:[dycryptData bytes]
length:[dycryptData length]
encoding:NSUTF8StringEncoding];
// prints (null)
NSLog(#"Sync timeis %#",dSync);
}
-(NSData *)blowfishDecrypt:(NSData *)messageData
usingKey:(NSData *)secretKeyData {
NSMutableData *decryptedData = [messageData mutableCopy];
BLOWFISH_CTX ctx;
Blowfish_Init (&ctx, (unsigned char*)[secretKeyData bytes], [secretKeyData length]);
NSRange aLeftRange, aRightRange;
NSData *aLeftBox, *aRightBox;
unsigned long dl = 0, dr = 0;
for (int i = 0; i< [decryptedData length]; i += 8) { // Divide data into octets...
// …and then into quartets
aLeftRange = NSMakeRange(i, 4);
aRightRange = NSMakeRange(i + 4, 4);
aLeftBox = [decryptedData subdataWithRange:aLeftRange];
aRightBox = [decryptedData subdataWithRange:aRightRange];
// Convert bytes into unsigned long
[aLeftBox getBytes:&dl length:sizeof(unsigned long)];
[aRightBox getBytes:&dr length:sizeof(unsigned long)];
// Decipher
Blowfish_Decrypt(&ctx, &dl, &dr);
// Put bytes back
[decryptedData replaceBytesInRange:aLeftRange withBytes:&dl];
[decryptedData replaceBytesInRange:aRightRange withBytes:&dr];
}
return decryptedData;
}
Blowfish library code can be found eg. here
HINT#1 //general answer
NSString provides an initializer for this purpose. You can see more info using the docs here.
NSString * dSync = [[NSString alloc] initWithData: dycryptData
encoding:NSUTF8StringEncoding];
Assuming you use ARC.
HINT#2 // the answer for this particular question
I tried your code and confirm the above NSString conversion returns null. So why it is not working? dycryptData is stream of bytes represented as hex, so I tried the following and received the desired result:
int dycryptData_len = [dycryptData length];
NSMutableString *dSync_hex = [NSMutableString stringWithCapacity:dycryptData_len*2];
const unsigned char *dycryptData_bytes = [dycryptData bytes];
for (int i = 0; i < dycryptData_len; ++i) {
[dSync_hex appendFormat:#"%02x", dycryptData_bytes[i]];
}
NSLog(#"dSync_hex=%#",dSync_hex);
I can see this result in log output:
dSync_hex=0eec37b62b76c2dfcdf723560f033ed8d6bd37dd5223bf665c318ebe07f3cf71

How to show content of NSData in bits?

I have NSData and I need to view its content in pure bits. Tried NSLog [NSData description] but it returns NSString. Any suggestions?
use this for bytes
const char *byte = [data bytes];
NSLog(#"%s",byte);
this is for bits
const char *byte = [data bytes];
unsigned int length = [data length];
for (int i=0; i<length; i++) {
char n = byte[i];
char buffer[9];
buffer[8] = 0; //for null
int j = 8;
while(j > 0)
{
if(n & 0x01)
{
buffer[--j] = '1';
} else
{
buffer[--j] = '0';
}
n >>= 1;
}
printf("%s ",buffer);
You can look at these bytes in memory browser window:
void* bytes_memory = [yourData bytes]; // set breakpoint after this line
... after stopping on breakpoint find bytes_memory in Local variables window, right click on it and choose View memory of *bytes_memory.
If you want to print to console bits (in format 10011100), then you will need to convert data into corresponding string representation (here is example).

Retrieve NSData to Hex by length

I got a NSData that contain bytes like <00350029 0033> with length 6, is there any correct way to split the bytes to array somehow like (00, 35, 00, 29, 00, 33) ?
NSData *data = ...;
NSMutableArray *bytes = [NSMutableArray array];
for (NSUInteger i = 0; i < [data length]; i++) {
unsigned char byte;
[data getBytes:&byte range:NSMakeRange(i, 1)];
[bytes addObject:[NSString stringWithFormat:#"%x", byte]];
}
NSLog(#"%#", bytes);
(Assuming you want the bytes as a hex string representation, as in your example. Otherwise, use NSNumber.)
You could use the NSData method
- (void)getBytes:(void *)buffer range:(NSRange)range
to get the bytes in a given range (after having allocated the right amount of memory, using malloc), then use
+ (id)dataWithBytes:(const void *)bytes length:(NSUInteger)length
to create new small (1 byte long) data objects which you then put into an array. However if you just retrieve the pointer to the bytes themselves (using [data bytes]), that gives you a pointer (kind of an array in the C sense, not an NSArray, but could also be used and far more efficient).
static NSString* HexStringFromNSData(NSData* data) {
NSUInteger n = data.length;
NSMutableString* s = [NSMutableString stringWithCapacity:(2 * n)];
const unsigned char* ptr = [data bytes];
for(NSUInteger i = 0; i < n; i++, ptr++) {
[s appendFormat:#"%02x", (long)*ptr];
}
return [NSString stringWithString:s];
}

How to convert an NSString to hex values

I'd like to convert a regular NSString into an NSString with the (what I assume are) ASCII hex values and back.
I need to produce the same output that the Java methods below do, but I can't seem to find a way to do it in Objective-C. I've found some examples in C and C++ but I've had a hard time working them into my code.
Here are the Java methods I'm trying to reproduce:
/**
* Encodes the given string by using the hexadecimal representation of its UTF-8 bytes.
*
* #param s The string to encode.
* #return The encoded string.
*/
public static String utf8HexEncode(String s) {
if (s == null) {
return null;
}
byte[] utf8;
try {
utf8 = s.getBytes(ENCODING_UTF8);
} catch (UnsupportedEncodingException x) {
throw new RuntimeException(x);
}
return String.valueOf(Hex.encodeHex(utf8));
}
/**
* Decodes the given string by using the hexadecimal representation of its UTF-8 bytes.
*
* #param s The string to decode.
* #return The decoded string.
* #throws Exception If an error occurs.
*/
public static String utf8HexDecode(String s) throws Exception {
if (s == null) {
return null;
}
return new String(Hex.decodeHex(s.toCharArray()), ENCODING_UTF8);
}
Update: Thanks to drawnonward's answer here's the method I wrote to create the hex NSStrings. It gives me an "Initialization discards qualifiers from pointer target type" warning on the char declaration line, but it works.
- (NSString *)stringToHex:(NSString *)string
{
char *utf8 = [string UTF8String];
NSMutableString *hex = [NSMutableString string];
while ( *utf8 ) [hex appendFormat:#"%02X" , *utf8++ & 0x00FF];
return [NSString stringWithFormat:#"%#", hex];
}
Haven't had time to write the decoding method yet. When I do, I'll edit this to post it for anyone else interested.
Update2: So the method I posted above actually doesn't output what I'm looking for. Instead of outputting hex values in 0-f format, it was instead outputting all numbers. I finally got back to working on this problem and was able to write a category for NSString that exactly duplicates the Java methods I posted. Here it is:
//
// NSString+hex.h
// Created by Ben Baron on 10/20/10.
//
#interface NSString (hex)
+ (NSString *) stringFromHex:(NSString *)str;
+ (NSString *) stringToHex:(NSString *)str;
#end
//
// NSString+hex.m
// Created by Ben Baron on 10/20/10.
//
#import "NSString+hex.h"
#implementation NSString (hex)
+ (NSString *) stringFromHex:(NSString *)str
{
NSMutableData *stringData = [[[NSMutableData alloc] init] autorelease];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [str length] / 2; i++) {
byte_chars[0] = [str characterAtIndex:i*2];
byte_chars[1] = [str characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[stringData appendBytes:&whole_byte length:1];
}
return [[[NSString alloc] initWithData:stringData encoding:NSASCIIStringEncoding] autorelease];
}
+ (NSString *) stringToHex:(NSString *)str
{
NSUInteger len = [str length];
unichar *chars = malloc(len * sizeof(unichar));
[str getCharacters:chars];
NSMutableString *hexString = [[NSMutableString alloc] init];
for(NSUInteger i = 0; i < len; i++ )
{
[hexString appendString:[NSString stringWithFormat:#"%x", chars[i]]];
}
free(chars);
return [hexString autorelease];
}
#end
The perfect and short way to convert nsstring to hexadecimal values
NSMutableString *tempHex=[[NSMutableString alloc] init];
[tempHex appendString:#"0xD2D2D2"];
unsigned colorInt = 0;
[[NSScanner scannerWithString:tempHex] scanHexInt:&colorInt];
lblAttString.backgroundColor=UIColorFromRGB(colorInt);
The macro used for this code is----
#define UIColorFromRGB(rgbValue)
[UIColor \colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
For these lines of Java
utf8 = s.getBytes(ENCODING_UTF8);
new String(decodedHexString, ENCODING_UTF8);
Objective-C equivalents would be
utf8 = [s UTF8String];
[NSString initWithUTF8String:decodedHexString];
To make an NSString with the hexadecimal representation of a character string:
NSMutableString *hex = [NSMutableString string];
while ( *utf8 ) [hex appendFormat:#"%02X" , *utf8++ & 0x00FF];
You will have to make your own decodeHex function. Just pull two characters out of the string and, if they are valid, add a byte to the result.
There is a problem with your stringToHex method - it drops leading 0s, and ignores 00s. Just as a quick fix, I made the below:
+ (NSString *) stringToHex:(NSString *)str
{
NSUInteger len = [str length];
unichar *chars = malloc(len * sizeof(unichar));
[str getCharacters:chars];
NSMutableString *hexString = [[NSMutableString alloc] init];
for(NSUInteger i = 0; i < len; i++ )
{
// [hexString [NSString stringWithFormat:#"%02x", chars[i]]]; /*previous input*/
[hexString appendFormat:#"%02x", chars[i]]; /*EDITED PER COMMENT BELOW*/
}
free(chars);
return [hexString autorelease];
}
Thanks to all who contributed on this thread. It was a great help to me. Since things have moved on a little since the original post, here's my updated implementation for iOS 6. I went with the categories approach, but chose to split the load between NSData and NSString. Comments welcomed.
First, the NSString half, which handles decoding a hex encoded string into an NSData object.
#implementation NSString (StringToHexData)
//
// Decodes an NSString containing hex encoded bytes into an NSData object
//
- (NSData *) stringToHexData
{
int len = [self length] / 2; // Target length
unsigned char *buf = malloc(len)
unsigned char *whole_byte = buf;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [self length] / 2; i++) {
byte_chars[0] = [self characterAtIndex:i*2];
byte_chars[1] = [self characterAtIndex:i*2+1];
*whole_byte = strtol(byte_chars, NULL, 16);
whole_byte++;
}
NSData *data = [NSData dataWithBytes:buf length:len];
free( buf );
return data;
}
#end
The changes were mostly for efficiency's sake: some simple old-fashioned pointer arithmetic means I could allocate the whole buffer in one go, and populate it byte by byte. Then the whole thing is passed to NSData in one go.
The encoding part, in NSData, looks like this:
#implementation NSData (DataToHexString)
- (NSString *) dataToHexString
{
NSUInteger len = [self length];
char * chars = (char *)[self bytes];
NSMutableString * hexString = [[NSMutableString alloc] init];
for(NSUInteger i = 0; i < len; i++ )
[hexString appendString:[NSString stringWithFormat:#"%0.2hhx", chars[i]]];
return hexString;
}
#end
Again, some minor changes, though I suspect no efficiency gains here. The use of "%0.2hhx" solved all the problems of missing leading zero's and ensures that only a single-byte is output at a time.
Hope this helps the next person taking this on!
One possible solution:
+(NSString*)hexFromStr:(NSString*)str
{
NSData* nsData = [str dataUsingEncoding:NSUTF8StringEncoding];
const char* data = [nsData bytes];
NSUInteger len = nsData.length;
NSMutableString* hex = [NSMutableString string];
for(int i = 0; i < len; ++i)[hex appendFormat:#"%02X", data[i]];
return hex;
}
So, first off, I would like to thank drawnonward for his answer. This gave me the first function, mean and clean. In the same spirit, I wrote the other one. Hope you like it.
#synthesize unsigned char* value= _value;
- (NSString*) hexString
{
_value[CONSTANT]= '\0';
unsigned char* ptr= _value;
NSMutableString* hex = [[NSMutableString alloc] init];
while ( *ptr ) [hex appendFormat:#"%02x", *ptr++ & 0x00FF];
return [hex autorelease];
}
- (void) setHexString:(NSString*)hexString
{
_value[CONSTANT]= '\0';
unsigned char* ptr= _value;
for (const char* src= [hexString cStringUsingEncoding:NSASCIIStringEncoding];
*src;
src+=2)
{
unsigned int hexByte;
/*int res=*/ sscanf(src,"%02x",&hexByte);
*ptr++= (unsigned char)(hexByte & 0x00FF);
}
*ptr= '\0';
}
My input was an digit base10 string, and the output should be the hex representation in string format. Examples:
#"10" -> #"A"
#"1128" -> #"468"
#"1833828235" -> #"6D4DFF8B"
Implementation:
+ (NSString *) stringToHex:(NSString *)str{
NSInteger result = [str integerValue];
NSString *hexStr = (result)?#"":#"0";
while (result!=0) {
NSInteger reminder = result % 16;
if(reminder>=0 && reminder<=9){
hexStr = [[NSString stringWithFormat:#"%ld",(long)reminder] stringByAppendingString:hexStr];
}else if(reminder==10){
hexStr = [#"A" stringByAppendingString:hexStr];
}else if(reminder==11){
hexStr = [#"B" stringByAppendingString:hexStr];
}else if(reminder==12){
hexStr = [#"C" stringByAppendingString:hexStr];
}else if(reminder==13){
hexStr = [#"D" stringByAppendingString:hexStr];
}else if(reminder==14){
hexStr = [#"E" stringByAppendingString:hexStr];
}else{
hexStr = [#"F" stringByAppendingString:hexStr];
}
result /=16;
}
return hexStr;
}
Perhaps you should use NSString dataUsingEncoding: to encode and initWithData:length:encoding: to decode. Depends on where you are getting the data from.

Saving/loading a 2D C array with NSKeyedArchiver

Malloc like this
int **terrain;
terrain = malloc(sizeof(int*) * mapSize.x);
for (int i = 0; i < mapSize.x; i++) {
terrain[i] = malloc(mapSize.y * sizeof(int));
}
Use it.
Convert to NSdata like this before saving
NSData *data=[NSData dataWithBytes:terrain length:(30*sizeof(int*) +30*30*sizeof(int) )];
[rootObject setValue:data forKey:#"terrain"];
[NSKeyedArchiver archiveRootObject: rootObject toFile: path];
loading into NSdata then converting back to int**
rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSData *data = [rootObject valueForKey:#"terrain"];
terrain =(int**) [data bytes];
With this code, is it saving the *int addresses then when I load the data it does not point to the correct data any more?
Or do I have a problem with the "endianness" as described in
Documentation
If it is the address issue, should i put a for loop when saving to convert *int to NSData then save all those and recreate the **int with another for loop/malloc?
I haven't tested this but I suspect that with the mallocs above there is no guarantee that you will have a continuous area of memory allocated.
what you could do is save the data separately for all mapSize.x array of bytes:
int **terrain;
terrain = malloc(sizeof(int*) * mapSize.x);
for (int i = 0; i < mapSize.x; i++) {
terrain[i] = malloc(mapSize.y * sizeof(int));
}
...
for (int j = 0; j < mapSize.x; j++)
{
NSData *data=[NSData dataWithBytes:terrain[j] length:(mapSize.y * sizeof(int))];
[rootObject setValue:data forKey:[NSString stringWithFormat:#"terrain%i", j]];
}
[rootObject setValue:mapSize.x forKey:#"terrain"];
[NSKeyedArchiver archiveRootObject:rootObject toFile:path];
I would convert the 2D array into NSArrays before archiving, because it will save you a lot of hassle.
NSMutableArray* terrainForArchiving = [NSMutableArray arrayWithCapacity:mapSize.x];
for(int col = 0; col < mapSize.x; ++col){
NSMutableArray* terrainCol = [NSMutableArray arrayWithCapacity:mapSize.y];
for(int row = 0; row < mapSize.y; ++row){
[terrainCol addObject:[NSNumber numberWithInt:terrain[col][row]]];
}
[terrainForArchiving addObject:terrainCol];
}
[NSKeyedArchiver archiveRootObject:terrainForArchiving];