How to convert NSData bytes into NSNumber or NSInteger? - iphone

There's a special NSString initWithData method for grabbing bits and converting them into string. However, I haven't found that in NSNumber class ref. Currently, I'm getting raw data (bytes) from a server in NSData format. I know how to do that in C, using memcpy and int pointers. But I am curious about what the convenience methods are for doing that straight from NSData. No conversion is needed. For example, I'm getting 00000010 byte, and I need to turn that into NSNumber of value 2, or NSInteger.

NSData is just a bucket for bytes and has no knowledge of the data contained therein. NSString's initWithData:encoding: method is a reciprocal (it does the opposite) of this method:
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
Therefore, to answer your question fully, it's important to know how your numbers were originally coerced into an NSData object. Once you know the encoding function, the search is for the reciprocal function.
From what you've included in the question, there may be a number of different solutions. However, you'll probably be able to use something along the following lines to convert into a usable numeric format using getBytes:length: on your NSData object. For e.g.
NSUInteger decodedInteger;
[myDataObject getBytes:&decodedInteger length:sizeof(decodedInteger)];
You can change the type of decodedInteger to whatever is appropriate for the bytes in your NSData object.

Try this:
NSNumber *num = [NSKeyedUnarchiver unarchiveObjectWithData:numberAsNSData];
Edit:
As pointed out by Matthias Bauch this will not work in your case. This only works if your NSNumber object was archived into NSData objects.

NSString to the rescue:
const unsigned char *bytes = [serverData bytes];
NSInteger aValue = [NSString stringWithFormat:#"%2x", bytes[0]].integerValue;
The docs warn about using NSScanner for localized decimal numbers, but that's of no concern in this case.

Here is the answer
//Integer to NSData
+(NSData *) IntToNSData:(NSInteger)data
{
Byte *byteData = (Byte*)malloc(4);
byteData[3] = data & 0xff;
byteData[2] = (data & 0xff00) >> 8;
byteData[1] = (data & 0xff0000) >> 16;
byteData[0] = (data & 0xff000000) >> 24;
NSData * result = [NSData dataWithBytes:byteData length:4];
NSLog(#"result=%#",result);
return (NSData*)result;
}
refer https://stackoverflow.com/a/20497490/562812 for more detail

Related

Bit conversion tool in Objective-C

Are there any built in utilities or macros in the objective-c libraries for iOS that will allow you to convert bytes to and from integers with respect to endianess?
Please don't tell me to use bit-shifting operations. I am trying to avoid writing custom code to do this if it already exists.
I would like the code to convert NSData* to primitive types (int, uint, short, etc) and to convert primitive types back to NSData*.
You can get the bytes from NSData by accessing the bytes property. Then just cast that to a pointer to whatever type you want. Obviously you'll need to ensure you know the endianness and size of what is in your NSData.
e.g.
#include <CFByteOrder.h>
// Bytes to uint32_t
NSData *data = <THE_DATA>;
void *bytes = [data bytes];
uint32_t *intBytes = (NSInteger*)bytes;
uint32_t swapped = CFSwapInt32BigToHost(*intBytes); ///< If the data in `data' is big endian
// uint32_t to bytes
uint32_t someInt = 1234;
uint32_t swappedInt = CFSwapInt32HostToBig(someInt); ///< If we want to store in big endian
NSData *data = [NSData dataWithBytes:&swappedInt length:sizeof(swappedInt)];
I think you want the CFSwapInt32* family of functions.
See Apple's docs.

i want to convert NSData To double value in Iphone

i want covert content of NSData Which is actually i need as a double type
how can i convert it?
here
1ff46c56 7dd86f40 nsdata byte and i want in double
Assuming your data is exactly 8 bytes, you can convert it to a double using memcpy(3):
double ConvertNSDataToDouble(NSData *data)
{
double d;
assert([data length] == sizeof(d));
memcpy(&d, [data bytes], sizeof(d));
return d;
}
Note that this assumes that the data is in native endian format. If you know that the data is big- or little-endian, then you may need to endian-swap the bytes first.
You can also do it like this (apart from Adam Rosenfield's answer).
This will work only if the data is UTF8 encoded.
NSString *dbleStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
double dble = [dbleStr doubleValue];
If the data is in endian format use one of the respective encoding formats from NSUTF16BigEndianStringEncoding, NSUTF16LittleEndianStringEncoding.
Note: The data should contain a double value. Otherwise you will get unexpected results.
Solution with less overhead
const double *double_ptr = [data bytes];
Examples of use is simply:
double val = double_ptr[0]; // the first double value in array
or
double val = *double_ptr;

iPhone SDK : NSString NSNumber IEEE-754

Can someone help me ? I have a NSString with #"12.34" and I want to convert it into a NSString with the same float number but in single precision 32bits binary floating-point format IEEE-754 : like #"\x41\x45\x70\xa4" (with hexa characters) or #"AEpĀ¤"...
I'm sure it's something easy but after many hours of reading the doc without finding a solution...
Thank you !
As Yuji mentioned, it's not a good idea to encode an arbitrary byte sequence into an NSString(although it can contain null bytes), as encoding transformations can(and probably WILL) destroy your byte sequence. If you want access to the raw bytes of a float, you may want to consider storing them as an NSData object(though I suggest you think through your reasons for wanting this first). To do this:
NSString *string = #"10.23";
float myFloat = [string floatValue];
NSData *myData = [[NSData alloc] initWithBytes:&myFloat length:sizeof(myFloat)];
If you want to get the raw bytes of a float, you could cast it, like so:
NSString *str = #"12.34";
float flt = [str floatValue];
unsigned char *bytes = (unsigned char *)&flt;
printf("Bytes: %x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
However the order in which these bytes are stored in the array depends on the machine. (See http://en.wikipedia.org/wiki/Endianness). For example, on my Intel iMac it prints: "Bytes: a4 70 45 41".
To make a new NSString from an array of bytes you can use initWithBytes:length:encoding:

objective-c converting strings to usable numbers

I have strings that look about like this:
stringA = #"29.88";
stringB = #"2564";
stringC = #"12";
stringD = #"-2";
what is the best way to convert them so they can all be used in the same mathmatical formula?? that includes add, subtract.multiply,divide etc
Probably floatValue (as it appears you want floating-point values), though integerValue may also be of use (both are instance methods of NSString).
[stringA doubleValue]
These are all wrong, because they don't handle errors well. You really want an NSNumberFormatter.
If you have the string #"abc" and try to use intValue or floatValue on it, you'll get 0.0, which is obviously incorrect. If you parse it with an NSNumberFormatter, you'll get nil, which is very easy to distinguish from an NSNumber (which is what would be returned if it was able to parse a number).
Assuming that you have NSString variables.
NSString *stringA = #"29.88";
NSString *stringB = #"2564";
NSString *stringC = #"12";
NSString *stringD = #"-2";
suppose, you want to convert a string value to float value, use following statement.
float x=[stringA floatValue];
suppose, you want to convert a string value to integer value, use following statement.
NSInteger y = [stringC intValue];
Hope, it helps to you.

Converting int64 to NSData

I need to convert a long value from int64 to NSData, so I can later run a hash algorithm on it. I perform:
int64_t longNumber = 9000000000000000000L;
NSMutableData *buffer = [NSMutableData dataWithBytes:&longNumber length:sizeof(longNumber)];
NSLog(#"%lld", [buffer bytes]);
NSLog(#"%lld", longNumber);
The resultant console output is like this:
6201314301187184
9000000000000000000
Why is NSData not properly storing the value of the long number? If I run this in a loop, the NSData bytes drift, starting with 620, then 621 and on. Am I outputting the address of the longNumber via [buffer bytes] and not its value?
You have two major issues: first, your number is too large for the long that you are casting it to. Instead of 9000000000000000000L you should have 9000000000000000000LL to indicate a long long constant.
Second, you answered your question correctly, you are printing out an address. Replace your NSLog line with with this line:
NSLog(#"%lld", *((int64_t*)[buffer bytes]));
and you should see the result you expect.