NSString value as NSData output - objective-c

I have a NSString which is #"15".
I want my NSData to be 15 also. I know how to convert it to get the value 31 35 but I would like my NSData to be 15 if I use NSLog on it. I'm not asking for a conversion but more for a translation. I don't wanna change the NSLog print but the NSData value. Is there anyway to do it ?

Parse the string to an integer (lets assume a signed 32-bit integer):
NSString *str = #"15";
int32_t i = (int32_t)[str intValue];
To encode it in native endian:
NSData *data = [NSData dataWithBytes:&i length:sizeof(i)];
Note: if you intend to transmit that data to another computer then you need to decide on a common endianness of primitive types. Big endian is traditionally used and facilitated with functions like htonl(), ntohl(), etc. If the computers are all the same platform then you can use the native endianness, for a slight performance boost and code simplification.

You need to convert the string to a byte first (by parsing it). Then you can build the NSData from the byte.

Related

NSData subStringFromIndex: Equivalent

I'm receiving a stream of NSData characters with around at least 50 characters. Usually, I would try and convert this to an NSString and use the subStringFromIndex: selector, but it seems like NSString is NULL terminating (correct me if I'm wrong) and I'd rather skip the data / string conversion. Does anyone know if there is a way to get the charecter at specific index in NSData? For example, say that the data returned is:
<12345678 9abcdefg hjiklmno>
Lets say I would like to get the 7 and the 8 out, and just those two alone. To get the 7 and 8, I've looked into trying something like this:
NSData *dataTrimmed = [data subdataWithRange:NSMakeRange(7, -19)];
Works like a charm. But the issue is, the stream is always going to be a different length. It could be 100 characters or it could be 50, but I always know that the two values I need are located at the 42nd and 43rd spot. Does anyone have an example of or know the best way to do this?
I wonder that your code with a negative length does not crash.
To get the two bytes at position 42, 43, just use
NSData *dataTrimmed = [data subdataWithRange:NSMakeRange(42, 2)];
Why do you want to skip the conversion to NSString?
The string you receive is encoded as NSData. Depending on the encoding each character will be represented as one or multiple bytes. If it is UTF8 encoded, some characters will be represented as one byte while other characters will be represented by two or more bytes.
For this reason, if you want your code be robust and handle different encodings and different string content you should first convert your NSData to a NSString and then index the string.
If your string is UTF-8 encoded you could do the following:
NSData *data = ...
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSString *subString = [str substringFromIndex:...
In my view, it only makes sense to skip converting to NSString if you receive a lot of data and you control both encoding and the contents of the string data you receive.
As the saying goes: Premature optimization is the root of all evil.

Xcode (Cocoa) how to write byte to NSData

Xcode...
I want to write one byte (1) to NSData. It seems very simple but im not able to find the proper link how to do it. I try to do that using unsigned char. But that stores the hex value.
You cannot add bytes to NSData use NSMutableData appendBytes:bytes length: method

Sending packets to Minecraft server: Objective c

I've been trying to send packets to a minecraft server from my custom Cocoa application (written in objective-c of course). I am a little confused as how to do that though. I did it in Java. That was very easy. Doing this is objective-c though is proving to be a bit more challenging.
This is the code that I am using:
- (void)handshake
{
PacketHandshake *packet = [PacketHandshake packetString:[NSString stringWithFormat:#"%#;%#:%i", username, IP, PORT]];
[packet writeData:dataOut];
}
Which calls:
- (void)writeData:(NSOutputStream *)dataOut
{
[super writeData:dataOut]; //Writes the "header" which is a char with the value of 0x02 (char packetID = 0x02)
NSUInteger len = [string lengthOfBytesUsingEncoding:NSUTF16BigEndianStringEncoding]; //Getting the length of the string i guess?
NSData *data = [string dataUsingEncoding:NSUTF16BigEndianStringEncoding]; //Getting string bytes?
[dataOut write:(uint8_t*)len maxLength:2]; //Send the length?
[dataOut write:[data bytes] maxLength:[data length]]; //Send the actual string?
}
I have established a successful connection to the server beforehand, but I don't really know whether or not I am sending the packets correctly. Could somebody please explain how I should send various data types and objects. (int, byte/char, short, double, NSString, BOOL/bool)
Also, is there any specific or universal way to send packets like the ones required by Minecraft?
Ok, I guess the question is now: how do data types, mainly strings, relate in Java and Objective-C?
Any help is appreciated, thank you!
Nobody knows?
Maybe you're running into a network/host byte order problem? I know very little about Minecraft- but I note that it's mentioned here that shorts in the Minecraft protocol use network byte order, which is big-endian (all other data types are 1 byte long so endianness is not relevant).
All x86 machines use little-endian.
I don't know whether your PacketHandshake class is converting the data before sending it- if not you could use the c library functions ntohs() and htons(), for which you'd need to include sys/types.h and
netinet/in.h
The link also mentions that strings are 64 byte array of standard ASCII chars, padded with 0x20s. You can get the ASCII value out of an NSString by doing [string UTF8String], which returns const char*- i.e. your standard C String ending with a 0x0, and then maybe pad it. But if it just works in Java, then maybe you don't need to.

NSData to NSString returns Null

I have searched. But still couldnt get it.
I'm converting NSdata to NSString.
When I do [data description];
it returns me <00000000 31323334 35363738>
Yes, Im receiving my string #"12345678".
How do I convert it to NSString appropriately?
I tried
NSString *b = [NSString stringWithUTF8String:[data bytes]];
NSString *a = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
Both returns me null.
Any idea?
Thanks
Hi all,
Thanks for all suggestion.
It appears to be constant whereby theres a null character infront always.
So whenever I receive something, i just remove the first <00000000>, then its working fine already
This happens if the encoding is incorrect.
Try using ASCII to test out. ASCII almost certainly work to retrive somekind of string. If it's only numbers it will probably work.
NSString *a = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSASCIIStringEncoding];
Most common except UTF-8 enconding is:
NSASCIIStringEncoding
NSUnicodeStringEncoding
NSISOLatin1StringEncoding
NSISOLatin2StringEncoding
NSSymbolStringEncoding
try them out and see if they work.
I'm converting NSdata to NSString. When I do [data description]; it
returns me <00000000 31323334 35363738> Yes, Im receiving my string
#"12345678".
No -- you aren't receiving that string. You are receiving a byte sequence that starts with a bunch of 0x00 values and is followed by a series of bytes that happen to correspond to the ASCII sequence "12345678".
I.e. you have raw data and are trying to convert it to a constrained type, but can't because the constrained type cannot represent the raw data.
You could try using the "lossy conversion" APIs on NSString, but that might not work and would be fragile anyway.
Best bet?
Only convert the bytes in the NSData that actually represent the string to an instance of NSString. That can be done with -initWithBytes:length:encoding:; you'll need to do the calculations to find the correct offset and length.
This may be because the first bytes of your data is 00. The character 0 is the end of string character. When creating a string from ASCII (from an array of chars or an array of bytes as you are doing), when the character 0 is encountered at the beginning, it produces an empty string.
I would however expect it to return an instance of NSString with 0 characters, and not null.

Extracting binary data out of an NSData object

I have an NSData object with a chunk of binary data and I'm trying to use getBytes:range: to set a primitive.
I can do this:
NSData* data = [...get record from file...]
double value = 0;
[data getBytes:&value range:NSMakeRange(42, 8)];
[someObject setValue:value];
I would rather not have to use a temporary variable as I have many fields in this file I need to read.
Is there an easy way (objc or c) to extract bytes out of an NSData object, cast these bytes to some primitive value, and assign it to an object without using some temporary?
Thanks!
It's not the prettiest, but you can get the raw data pointer used by NSData and dereference it in the proper location.
UInt8 *rawData = [theData bytes];
[someObject setValue:*((double*)(&rawData[42]))];
This involves lots of casting, but you only need to use one temporary variable instead of one for each data type, and it will be slightly faster as you don't repeatedly ask the NSData object for a specific range of data.