pohl
pohl

Reputation: 3175

iOS custom file format loading with NSData & NSCoding

I'm looking for some guidance from some iOS Cocoa programmers as to how one might implement a mechanism to load and parse a custom file format into the model objects that I'll be using in memory. I know there must be many ways to crack this nut, but let me share the basic idea of the current path I've explored, and where I became stuck.

But first, here is the context: say I have an existing file format that I cannot change. It's basically an exotic pipe-delimited format that is broken into various sections, each of which starts something like this:

%n|sectionName

...and the n lines that follow are all pipe-delimited in a way that is unique to that section. Some sections have a pipe-delimited header line, followed by n lines of data (also pipe-delimited), and other sections might just have n pipe-delimited lines. There are several short sections towards the beginning of the file, and then finally there will be one huge section that describes the nodes of a k-ary tree: their parent-child relationships and any data associated with each node. All told the size of these files is in the tens of megabytes, perhaps larger in the future.

Finally, the last bit of context is that I'm fairly new to iOS programming.

I started by using NSFileHandle to obtain a representation of the file as an instance of NSData. This was pretty easy, and upon exploring the NSData interface and trying how to proceed from there, I notice the NSCoding protocol, which purports to be a facility for archiving and serialization of objects into (and from) representations.

I thought this sounded like something I might need, since I tend to think of file formats as being just representations that my model objects can be marshaled into. After digging into the "Archives and Serializations Programming Guide", however, I began to second-guess myself. The API didn't seem to lend itself to what I'm trying to accomplish.

Am I going down a blind alley here? Should I be seeking to subclass NSInputStream instead, or should I take some other approach that I'm missing?

Upvotes: 1

Views: 1200

Answers (4)

Gary W. Longsine
Gary W. Longsine

Reputation: 662

There are a few open source parsing related kits, each targeting slightly different purposes. One or none of this might be useful to you, but mentioning them in response to your question seems like it might be useful to others, at least.

Upvotes: 1

Jeremy W. Sherman
Jeremy W. Sherman

Reputation: 36143

I recommend using Ragel to handle the parsing smarts. It should be much easier than using NSScanner once you have the basic scaffolding in place to set up the parser and feed bytes into it until parsing finishes.

What objects you want to use to store the parsed results in is up to you. It shouldn't be too hard to build your object graph using action functions triggered by state machine transitions.

How you want to get bytes to feed into Ragel is also up to you. You can use C standard IO streams, Foundation streams, or Foundation file handles. All Ragel cares about is getting its hands on a buffer of characters so it can run it through the state machine your description was compiled into.

NSCoder is likely to be more trouble than it's worth for your purposes. It expects to be used as a way to persist and decode an Obj-C object, with the coding/decoding driven by the object's demands ("Okay, now gimme an int, now a short, how's about an Obj-C object now…").

Upvotes: 2

Anomie
Anomie

Reputation: 94794

NSCoding is probably the wrong approach. It's designed for serializing and unserializing Objective-C types, not parsing a custom file format.

There's probably no need to subclass NSInputStream either. Your best bet here is probably to use C's stdio library, in particular fgets to read the lines. If you really want to use NSInputStream or NSFileHandle you certainly can, you'll just have to parse out each line from the string yourself (which is really not that hard).

Upvotes: 3

GorillaPatch
GorillaPatch

Reputation: 5057

As you pointed out correctly, there are more than one ways to crack this nut. Unfortunately you did not point out what you want to do with the parsed data and if you want to write out the file in the end.

First, for parsing one has to think if it would make sense to use Objective-C at all. I could think of writing a small helper Perl script which is very suitable for parsing text files and write the output to an XML file or better a plist file. This file could then be read in with your Objective-C code and you could work with the data. You could also choose to write the data into a sqlite database which is also a suitable file format as there are data connectors for a wide area of languages available (C, Perl, Python, etc.).

Second, if you want to parse the text file a class worth having a look at is NSLineScanner which is used to parse a text file.

I do not see any benefits using NSInputStream as it returns only raw bytes.

Edit

This preprocessing using another language is not possible on iOS devices AFAIK. So this option is only possible on the mac.

Upvotes: 1

Related Questions