Converting NSArray of NSString elements into binary?

  • Newb Cocoa question:

    I have many lines of textual ascii data in a file that i need to scan
    into a NSData as binary:
        000 255 127 255 066 033 127 000 221 ...
    This data can go for more than 1000 values per line.

    Currently I read each line into a NSString and parse the data into a
    NSArray:
        NSString *list = @"000 255 127 255 066 033 127 000
    221 ...";    // example data
        NSArray *listItems = [list componentsSeparatedByString:@" "];

    Is there some method to convert the NSArray of NSString elements into
    binary byte values? Or do I have to go through each element and
    convert each NSString into a NSNumber so I can put it's byteValue
    into a NSMutableData one by one? Is this the wrong approach?

    Russ
  • On Oct 1, 2007, at 5:28 PM, R.L. Grigg wrote:

    > Is there some method to convert the NSArray of NSString elements
    > into binary byte values?

    No.

    > Or do I have to go through each element and convert each NSString
    > into a NSNumber so I can put it's byteValue into a NSMutableData
    > one by one? Is this the wrong approach?

    Using NSNumber is a little extreme; just using -intValue ought to
    cover things unless you need 64-bit integers.

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • On Oct 1, 2007, at 6:05 PM, Nick Zitzmann wrote:
    >
    > On Oct 1, 2007, at 5:28 PM, R.L. Grigg wrote:
    >
    >> Is there some method to convert the NSArray of NSString elements
    >> into binary byte values?
    >
    > No.
    >
    >> Or do I have to go through each element and convert each NSString
    >> into a NSNumber so I can put it's byteValue into a NSMutableData
    >> one by one? Is this the wrong approach?
    >
    > Using NSNumber is a little extreme; just using -intValue ought to
    > cover things unless you need 64-bit integers.

    Hmm, I wish there was a -charValue method for NSString. This still
    needs a step to go from the integers that intValue gives me to byte
    values for putting into NSData. I guess there's no graceful way to
    accomplish this.
    Russ
  • On Oct 1, 2007, at 7:04 PM, R.L. Grigg wrote:
    > On Oct 1, 2007, at 6:05 PM, Nick Zitzmann wrote:
    >> On Oct 1, 2007, at 5:28 PM, R.L. Grigg wrote:
    >>> Is there some method to convert the NSArray of NSString elements
    >>> into binary byte values?
    >> No.
    >>> Or do I have to go through each element and convert each NSString
    >>> into a NSNumber so I can put it's byteValue into a NSMutableData
    >>> one by one? Is this the wrong approach?
    >> Using NSNumber is a little extreme; just using -intValue ought to
    >> cover things unless you need 64-bit integers.
    > Hmm, I wish there was a -charValue method for NSString. This still
    > needs a step to go from the integers that intValue gives me to byte
    > values for putting into NSData. I guess there's no graceful way to
    > accomplish this.

    I may be missing something, but you could always archive the NSArray
    instance using NSArchiver (then unarchive via NSUnarchiver).

    Yah -- that'll bloat the size a bit, but you'll not have to deal with
    any endianness issues, etc...

    b.bum
  • On Oct 1, 2007, at 7:10 PM, Bill Bumgarner wrote:
    > On Oct 1, 2007, at 7:04 PM, R.L. Grigg wrote:
    >> On Oct 1, 2007, at 6:05 PM, Nick Zitzmann wrote:
    >>> On Oct 1, 2007, at 5:28 PM, R.L. Grigg wrote:
    >>>> Is there some method to convert the NSArray of NSString elements
    >>>> into binary byte values?
    >>> No.
    >>>> Or do I have to go through each element and convert each
    >>>> NSString into a NSNumber so I can put it's byteValue into a
    >>>> NSMutableData one by one? Is this the wrong approach?
    >>> Using NSNumber is a little extreme; just using -intValue ought to
    >>> cover things unless you need 64-bit integers.
    >> Hmm, I wish there was a -charValue method for NSString. This still
    >> needs a step to go from the integers that intValue gives me to
    >> byte values for putting into NSData. I guess there's no graceful
    >> way to accomplish this.
    >
    > I may be missing something, but you could always archive the
    > NSArray instance using NSArchiver (then unarchive via NSUnarchiver).
    >
    > Yah -- that'll bloat the size a bit, but you'll not have to deal
    > with any endianness issues, etc...

    Wow now I'm confused. If these are byte values in NSData how does the
    endianness factor in?
    Russ
  • On Oct 1, 2007, at 7:22 PM, R.L. Grigg wrote:
    > On Oct 1, 2007, at 7:10 PM, Bill Bumgarner wrote:
    >> On Oct 1, 2007, at 7:04 PM, R.L. Grigg wrote:
    >>> On Oct 1, 2007, at 6:05 PM, Nick Zitzmann wrote:
    >>>> On Oct 1, 2007, at 5:28 PM, R.L. Grigg wrote:
    >>>>> Is there some method to convert the NSArray of NSString
    >>>>> elements into binary byte values?
    >>>> No.
    >>>>> Or do I have to go through each element and convert each
    >>>>> NSString into a NSNumber so I can put it's byteValue into a
    >>>>> NSMutableData one by one? Is this the wrong approach?
    >>>> Using NSNumber is a little extreme; just using -intValue ought
    >>>> to cover things unless you need 64-bit integers.
    >>> Hmm, I wish there was a -charValue method for NSString. This
    >>> still needs a step to go from the integers that intValue gives me
    >>> to byte values for putting into NSData. I guess there's no
    >>> graceful way to accomplish this.
    >>
    >> I may be missing something, but you could always archive the
    >> NSArray instance using NSArchiver (then unarchive via NSUnarchiver).
    >>
    >> Yah -- that'll bloat the size a bit, but you'll not have to deal
    >> with any endianness issues, etc...
    >
    > Wow now I'm confused. If these are byte values in NSData how does
    > the endianness factor in?

    It probably doesn't -- I didn't parse that word. :)

    But, still, the least # of lines of code would be NSArchiver/
    NSUnarchiver.  The question boils down to what you want to do with
    the NSData.  If you need to interpret the contents outside using
    NSUnarchiver, then you'll need to do something more manual.

    If you just need an array of bytes, malloc() isn't that hard.

    b.bum
  • Hi Russ,

    At the risk of summary ostracization by the list, I'll suggest that
    this might be an appropriate place to use classic C stdio tools. I
    use something like the following to read binary from a text file
    containing hex byte representations to an unsigned char * byte array
    originalPixels (which is a a "frame buffer", which is why the nested
    loops):

    #include <stdio.h>
    .
    .
    .
    /* file name is in NSString *fileName */

    unsigned char *originalPixels;
    int x, y, result, pix;
    FILE *f;

    [fileName getCString:fname];

    f = fopen(fname, "r");
    if (!f) {
      printf("coin file %s could not be opened\n", fname);
      return;
    }

      for (y=0; y<h; y++) {
      for (x=0; x<w; x++) {
        result = fscanf(f, "%x", &pix);
        if (EOF == result) {
        /* your error handling here */
        }
        originalPixels[y*w + x] = (unsigned char)pix;
      }
      }

    (warning: parts of the above typed in Mail)

    The intermediate variable pix is not really needed, but it can make
    debugging easier.

    Replace the %x in fscanf() with %d for decimal text representation.
    The %d or %x skips all leading whitespace including newlines, so
    shouldn't matter how many numbers you have on a line.

    The Cocoa approach looks like a bit more of a struggle than the above.

    ScottB

    On Oct 2, 2007, at 11:04 , R.L. Grigg wrote:

    > On Oct 1, 2007, at 6:05 PM, Nick Zitzmann wrote:
    >>
    >> On Oct 1, 2007, at 5:28 PM, R.L. Grigg wrote:
    >>
    >>> Is there some method to convert the NSArray of NSString elements
    >>> into binary byte values?
    >>
    >> No.
    >>
    >>> Or do I have to go through each element and convert each NSString
    >>> into a NSNumber so I can put it's byteValue into a NSMutableData
    >>> one by one? Is this the wrong approach?
    >>
    >> Using NSNumber is a little extreme; just using -intValue ought to
    >> cover things unless you need 64-bit integers.
    >
    > Hmm, I wish there was a -charValue method for NSString. This still
    > needs a step to go from the integers that intValue gives me to byte
    > values for putting into NSData. I guess there's no graceful way to
    > accomplish this.
    > Russ
    >
  • On Oct 1, 2007, at 8:04 PM, R.L. Grigg wrote:

    > Hmm, I wish there was a -charValue method for NSString.

    There is; -characterAtIndex:. Or, if you need the char array, then
    use -cStringUsingEncoding: or -UTF8String.

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • On Oct 1, 2007, at 7:27 PM, Scott F Bayes wrote:
    > Replace the %x in fscanf() with %d for decimal text representation.
    > The %d or %x skips all leading whitespace including newlines, so
    > shouldn't matter how many numbers you have on a line.
    >
    > The Cocoa approach looks like a bit more of a struggle than the above.

    Scott,
    I'm beginning to think so too. I just discovered that NSString
    componentsSeparatedByString:@" " is not the same thing as
    componentsSeparatedByWhiteSpace, which doesn't exist, making the
    Cocoa approach not so useful in my situation. :(

    Your clever idea to use fscanf with C indexing hadn't occurred to me.
    I will pursue this route.
    Thanks!
    Russ
  • On Oct 1, 2007, at 7:27 PM, Scott F Bayes wrote:

    > At the risk of summary ostracization by the list,
    > [...]
    > [fileName getCString:fname];
    >
    Well, here's the summary ostracism:

    *Do not use getCString.*

    It's deprecated.  See <http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes
    /NSString_Class/DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref
    /occ/instm/NSString/getCString:
    >.

    If you want to retrieve the characters, specify an encoding or use
    getCharacters:.
    In the current context, dataUsingEncoding: looks like it may meet the
    OP's needs.
    Although it's still not clear exactly what use will be made of the
    data in the end...

    mmalc
  • Surprisingly, mmalc did not list the API you should use with fread or
    other POSIX-based APIs.
    Just for the record, it's -fileSystemRepresentation.
    In a pinch, UTF8String also works, but it's not recommended (in some
    corner cases the result is slightly different, but POSIX compensates
    for that anyway so it's not a big issue for practical use).

    On Oct 1, 2007, at 8:39 PM, mmalc crawford wrote:

    >
    > On Oct 1, 2007, at 7:27 PM, Scott F Bayes wrote:
    >
    >> At the risk of summary ostracization by the list,
    >> [...]
    >> [fileName getCString:fname];
    >>
    > Well, here's the summary ostracism:
    >
    > *Do not use getCString.*
    >
    > It's deprecated.  See <http://developer.apple.com/documentation/
    > Cocoa/Reference/Foundation/Classes/NSString_Class/
    > DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/occ/
    > instm/NSString/getCString:>.
    >
    > If you want to retrieve the characters, specify an encoding or use
    > getCharacters:.
    > In the current context, dataUsingEncoding: looks like it may meet
    > the OP's needs.
    > Although it's still not clear exactly what use will be made of the
    > data in the end...
    >
    > mmalc
  • You're very welcome.

    ScottB

    On Oct 2, 2007, at 11:48 , R.L. Grigg wrote:

    > On Oct 1, 2007, at 7:27 PM, Scott F Bayes wrote:
    >> Replace the %x in fscanf() with %d for decimal text
    >> representation. The %d or %x skips all leading whitespace
    >> including newlines, so shouldn't matter how many numbers you have
    >> on a line.
    >>
    >> The Cocoa approach looks like a bit more of a struggle than the
    >> above.
    >
    > Scott,
    > I'm beginning to think so too. I just discovered that NSString
    > componentsSeparatedByString:@" " is not the same thing as
    > componentsSeparatedByWhiteSpace, which doesn't exist, making the
    > Cocoa approach not so useful in my situation. :(
    >
    > Your clever idea to use fscanf with C indexing hadn't occurred to
    > me. I will pursue this route.
    > Thanks!
    > Russ
    >
    >
  • Very summary! But not really ostracism.

    In my case, the file name was generated by a primitive c program on a
    PC, and is guaranteed to be straight ASCII; I should have mentioned
    that in my original response, but I had made my decision about how to
    acquire the char * version of the file name many months ago, and
    forgot that I'd already examined the issue (I did know it was
    deprecated, but forgot).

    The bigger risk of course is that the deprecated method might turn
    into a pumpkin, perhaps when a new Xcode is released. Oops! This is
    October already...

    Thanks for the reminder :-)

    > Although it's still not clear exactly what use will be made of the
    > data in the end...

    From what I saw in his post, it may be pixel data from some other
    program, stored in the file as ASCII decimal values. That's what mine
    is.

    ScottB

    On Oct 2, 2007, at 12:39 , mmalc crawford wrote:

    >
    > On Oct 1, 2007, at 7:27 PM, Scott F Bayes wrote:
    >
    >> At the risk of summary ostracization by the list,
    >> [...]
    >> [fileName getCString:fname];
    >>
    > Well, here's the summary ostracism:
    >
    > *Do not use getCString.*
    >
    > It's deprecated.  See <http://developer.apple.com/documentation/
    > Cocoa/Reference/Foundation/Classes/NSString_Class/
    > DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/occ/
    > instm/NSString/getCString:>.
    >
    > If you want to retrieve the characters, specify an encoding or use
    > getCharacters:.
    > In the current context, dataUsingEncoding: looks like it may meet
    > the OP's needs.
    > Although it's still not clear exactly what use will be made of the
    > data in the end...
    >
    > mmalc
    >
    >
    >
    >
previous month october 2007 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Go to today