How to read a specific line from a large text file using Objective-C?

Let's say I have a text file my.txt like this

this is line 1 this is line 2 .... this is line 999999 this is line 1000000 

On Unix, I can get the line "this is line 1000" by issuing the command "head -1000 my.txt | tail -1". What is the appropriate way to get this in Objective-C?

+4
source share
4 answers

If this is not too inefficient in order to immediately get the whole thing in memory, then the most compact sequence of calls (which I expanded to several lines for easier presentation):

 NSError *error = nil; NSString *sourceString = [NSString stringWithContentsOfFile:@"..." encoding:NSUTF8StringEncoding error:&error]; NSArray *lines = [sourceString componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]]; NSString *relevantLine = [lines objectAtIndex:1000]; 

You must check the error and count for lines to check.

EDIT: For comparison with Nathan's answer, the advantage of character separation in a set is that you accept any of the five Unicode characters that can delimit a line break anywhere where several of them sit next to each other counting only one gap (like e.g. \r\n ).

NSInputStream , you probably have to deal with the fact that the memory issue is a problem that barely evolves than C stdio.h fopen / fread / etc, so you have to write your own little loop to scroll.

+3
source

The simplest is simply to upload the file using one of the NSString file methods, and then use the [NSString componentsSeparatedByString:] method to get an array of each row.

Or you can use NSScanner to scan newlines / carriage returns, counting them until you get the line you are interested in.

If you are really worried about memory usage, you can see how NSInputStream uses this to read in a file, preserving the number of new lines. It is a shame that NSScanner does not work with NSInputStream.

+1
source

I do not think this is an exact duplicate, because it seems that you want to skip some lines in the file, but you can easily use an approach like here:

Objective-C: reading line by line ( Specific answer , which has sample code)

Loop on the input file, read in a piece of data and search for new lines. Count them, and when you press the desired number, output the data after this and until the next.

Your example looks like you might have hundreds of thousands of lines, so definitely don't just read the file in NSString and certainly don't convert it to NSArray.

If you want to do this using the fancier NSInputStream method (which has some key advantages in decoding a character set), here is a great example that shows the basic idea of ​​polling to consume all the data from the stream source (in the example file, its a bit redundant). Its for output, but the idea is also suitable for input: Poll versus run loop

+1
source

The answer does not explain how to read the file too LARGE to save in memory. Objective-C does not have a good solution for reading large text files without putting them into memory (which is not always an option).

In this case, I like to use c methods:

 FILE* file = fopen("path to my file", "r"); size_t length; char *cLine = fgetln(file,&length); while (length>0) { char str[length+1]; strncpy(str, cLine, length); str[length] = '\0'; NSString *line = [NSString stringWithFormat:@"%s",str]; % Do what you want here. cLine = fgetln(file,&length); } 

Note that fgetln will not save your newline character. In addition, We +1 is the length of str, because we want to create space to end NULL.

0
source

All Articles