5

I have the NSData-to-NSString conversion in an NSData Category, because I'm always using the NSString method: initWithData:encoding:. But, according to this answer, https://stackoverflow.com/a/2467856/1231948, it is not that simple.

So far, I have this method in my NSData Category, in an effort to keep consistent with methods in other data objects that return a string from a method with the same name:

- (NSString *) stringValue
{
    return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
}

So far it is successful, but I would like to determine if a string is null-terminated, to decide whether I should use this method instead, also from the answer link:

NSString* str = [NSString stringWithUTF8String:[data bytes]];

How do I determine if UTF-8 encoded NSData contains a null-terminated string?


After getting the answer below, I wrote more thorough implementation for my NSData Category method, stringValue:

- (NSString *) stringValue
{
    //Determine if string is null-terminated
    char lastByte;
    [self getBytes:&lastByte range:NSMakeRange([self length]-1, 1)];

    NSString *str;

    if (lastByte == 0x0) {
        //string is null-terminated
        str = [NSString stringWithUTF8String:[self bytes]];
    } else {
        //string is not null-terminated
        str = [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
    }

    return str;
}
Community
  • 1
  • 1
Sheamus
  • 6,506
  • 3
  • 35
  • 61
  • From where are you getting the data? It should not be variable or a mystery if the data is null-terminated. For example, you apparently have some assurance that it's encoded as UTF-8. Whatever protocol dictates that should also dictate whether it's null-terminated. (If you don't have assurance that it is or is not null-terminated, for example, how can you be sure it's not a sequence of multiple null-terminated strings? Or multiple strings separated by nulls, which is slightly different?) – Ken Thomases Jan 15 '15 at 04:59
  • I'm not trying to give assurance, but rather generality--I'm trying to build a solution that is robust enough to handle data in a wide array of situations. You're right, I'm limiting to UTF-8 for two reasons--1) UTF-8 is the most widely used character encoding online (over 80%), and is recommended by W3C as the standard encoding for languages such as HTML and XML, 2) since UTF-8 is the standard in most cases, I would want to reserve the handling of other encodings in a separate method that would take an encoding as the second parameter, which is how Java's API was designed in later versions. – Sheamus Jan 15 '15 at 06:28
  • In my experience, data coming from a known source is not guaranteed to be null-terminated. Things happen during transmission and that final 0 may or may not arrive. Good question. – Elise van Looij Jul 08 '18 at 14:05

2 Answers2

10

Null termination literally means that the last byte has a value of zero. It's easy to check for:

char lastByte;
[myNSData getBytes:&lastByte range:NSMakeRange([myNSData length]-1, 1)];
if (lastByte == 0x0) {
    // string is null terminated
} else {
    // string is not null terminated
}
Tom Harrington
  • 69,312
  • 10
  • 146
  • 170
  • This is exactly what you need when you run into trouble converting NSData to NSString. See kennytm's answer at: https://stackoverflow.com/questions/2467844/convert-utf-8-encoded-nsdata-to-nsstring. To summarize: if the NSData is null-terminated use [NSString stringWithUTF8String:[theData bytes]], else use [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding]. – Elise van Looij Jul 08 '18 at 14:40
0

So you wish to determine whether the last byte of your NSData is a null, you know how to get a pointer to all the bytes (bytes) and how many there are (length).

In C a "pointer to all the bytes" can be used as an array and indexed, so you can get the last byte using:

Byte *theBytes = data.bytes;
Byte lastByte = theBytes[bytes.length - 1];

If you need to support the null-terminated string being shorter then the full buffer you'll have to scan for it, remembering to stop at the end (so don't use something like strlen).

In checking for the null you will get both a pointer to the bytes and the length, given that you might want to use initWithBytes:length:encoding: to construct the NSString rather than either of the two methods in the question.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86