HOWTO? reading text files in cocoa

I want to read a text file. The NSInputStream class will read bytes into an array. The NSString class will load a string from a file. (I can't get these to work due to BAD ACCESSEXC, which is probably another story.) What I need is a way to read a text file line-by-line into a NSString object.

This seems like a routine programming need which should be readily available, but I'm stumped.

Any help is appreciated.

Thank you

CODE SNIPPET (square brackets don't appear in forum for some reason)
NSString* line;
NSInputStream* stream = [NSInputStream inputStreamWithFileAtPath:@"/Users/pkvermont/FileTest/FileTest.m"];
while ([stream hasBytesAvailable])
{ [stream readLine: line]; <<<< no such method, but what goes here?
}
[stream close];

END SNIPPED

MacBook, Mac OS X (10.4.8)

Posted on Oct 20, 2007 4:41 PM

Reply
7 replies

Oct 20, 2007 5:11 PM in response to pkvermont

First of all, to put code on Apple forums, you have to use the markup { code } (without spaces) for example :
{ code }
// my code
{ code }

Gives without spaces in the braces :

// my code


Knowing that you can write your code properly 😀

Now, about your problem, Cocoa is neither C++ nor Java, it doesn't use "streams" to read files. the NSStream class and subclasses are to use with data streams like network ones for example.
Your problem is most likely to be solved with NSData class and its subclass NSMutableData which can manage file contents, using -initWithContentsOfFile: method you can simply retrieve your file content and parse it the way you like.

Oct 21, 2007 4:15 PM in response to pkvermont

pkvermont wrote:
I want to read a text file. The NSInputStream class will read bytes into an array. The NSString class will load a string from a file. (I can't get these to work due to BAD ACCESSEXC, which is probably another story.)


No doubt.

What I need is a way to read a text file line-by-line into a NSString object.


Why?

This seems like a routine programming need which should be readily available, but I'm stumped.


Very few people really need to code this type of logic from scratch. It would be better to explain just what you are trying to accomplish.

Oct 22, 2007 6:29 AM in response to etresoft

What I am trying to accomplish:

I have a text file with names, addresses, telephone numbers and other information about people. The programming will read this file and organize it hierarchically on the screen. The file was created by a .NET program I want to replace on the Mac.

File data looks like this:

NATEntry
name = Smithee, Alan
telephone = 800-123-4567
birthdate = 10/20/1930
print = yes
endEntry


(Yes, I know XML was built for this stuff.)

Thanks

Oct 22, 2007 8:50 AM in response to pkvermont

To try and get Cocoa to read such a file line by line just isn't interesting. Cocoa isn't set up to do that kind of work, so it would be both not interesting and not trivial.

There are several ways to approach this problem. How big is this text file going to be? If it is a small file (less than 50 megabytes), just let Cocoa do the work for you. You can read the entire file into a string, then do "rangeOfString" or "rangeOfCharactersInSet" to walk through string, looking for "NATEntry" and "endEntry". You'll probably have to use "rangeOfCharactersInSet" to properly handle whatever line ending the .NET program is using. That is about as low-level and difficult as Cocoa gets.

Personally, I would consider it much more fun to span a Perl process to do the work for me. The RegEx would look something like:

s/^NATEntry$^([^=]+)$^s(.*)s$^endEntry$/gsm;

(I haven't tried this regex and I don't know if it will work. Part of the fun is figuring that out.)

Basically, just write a Perl script that takes such a .NET file (read over standard input) and then formats it into XML and prints it out on standard output. Your Cocoa script will then spawn that Perl process, rerouting its input to be that file and its output to a pipe back to itself. Then, treat the output of that Perl script as Propertylist data (which it will be) and store it into an NSDictionary. At that point, you have truly converted the file into a native MacOS X format. You can do anything you want with it.

That is an interesting way to approach this problem. If you are interested, I would be more than happy to help. If you just want to parse the text file, you'll have to figure that out on your own. Trust me though, what I have described is very little code (either Perl or Cocoa) and would be very robust. Hand-rolled line parsing code would be harder and less reliable.

Oct 22, 2007 9:48 AM in response to pkvermont

pkvermont,

The straightforward way to do this in Cocoa is:

NSString *filepath = @"/Users/path/to/file/to/parse";
NSString *file;
NSArray *results;
//Get file into string
file = [NSString stringWithContentsOfFile:filepath];
//Parse lines into an NSArray;
results = [file componentSeperatedByString:@" "]; // Assumes Mac line end 'return'
NSLog(@"First line: %@",[results objectAtIndex:0]; //Prints out the first line captured to Run Log


This will give you each line from the file in an NSArray for easy reference. You could then proceed to parse each line - discarding blank lines and the entry markers - using NSScanner to find the "= " and the taking the rest of the data after that point, but it would be laborious. You might be able to get something more usable parsing on "= " and then throwing away more lines. But if this is a one time import and not a continuing process I would work to massage the entry data into something that is already parsed or at least stripped of blank line entries etc.

Eventually you're probably looking to get these into an NSArray of NSDictionaries and you could do this programatically once you have separated the data. Then saving the data in an XMLish format for loading and re-saving is trivial. But as suggested there's probably a better non-Cocoa way to do this but hopefully this will get you started on learning Cocoa if this is a learning exercise for you.

HTH,

=Tod

Oct 24, 2007 12:56 PM in response to pkvermont

I (finally) realized Obj-C is, well, C. I could read the file using stdio.h functions, then move the data into Cocoa/NS objects.


char buffer[1000];
FILE* file = fopen("/Users/pkvermont/FileTest/FileTest.h", "r");
while(fgets(buffer, 1000, file) != NULL)
{ NSString* string = [[NSString alloc] initWithCString:buffer];
NSLog(string);
}//while
fclose(file);


I appreciate the help and answers. I will/should move past this text file issue someday ... soon, I hope.

Thanks.

Oct 24, 2007 12:57 PM in response to pkvermont

I (finally) realized Obj-C is, well, C. I could read the file using stdio.h functions, then move the data into Cocoa/NS objects.


char buffer[1000];
FILE* file = fopen("/Users/pkvermont/FileTest/FileTest.h", "r");
while(fgets(buffer, 1000, file) != NULL)
{ NSString* string = [[NSString alloc] initWithCString:buffer];
NSLog(string);
}//while
fclose(file);


I appreciate the help and answers. I will/should move past this text file issue someday ... soon, I hope.

Thanks.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

HOWTO? reading text files in cocoa

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.