Fred Whitefield
Fred Whitefield

Reputation: 33

Count number of newlines in a file

What is the smallest code I can use to count the number of occurrences of the newline character in a file with objective-c / cocoa touch?

Thanks!

Upvotes: 3

Views: 1196

Answers (5)

aidaan
aidaan

Reputation: 41

If you want to stay within Cocoa/CocoaTouch, you can use NSRegularExpression for this:

NSString *theString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\n" options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numLines = [regex numberOfMatchesInString:theString options:0 range:NSMakeRange(0, [theString length])] + 1;

Upvotes: 0

cobbal
cobbal

Reputation: 70733

smallest you say? That automatically turns this question into code golf

FILE*f=fopen(path,"r");
int i,c;
while(1+c)i+=(c=fgetc(f))==10;
printf("%i",i);

(please don't ever actually use this code)

Upvotes: 0

Dave DeLong
Dave DeLong

Reputation: 243156

Both of the other answers are correct, but with the caveat that they require loading the entire file into memory to work.

The way around that is to load the file incrementally using an NSFileHandle. Something like this:

NSFileHandle * file = [NSFileHandle fileHandleForReadingAtPath:pathToFile];
NSUInteger chunkSize = 1024;
NSData * chunk = [file readDataOfLength:chunkSize];
NSUInteger numberOfNewlines = 0;
while ([chunk length] > 0) {
  const unichar * bytes = (const unichar *)[chunk bytes];
  for (int index = 0; index < [chunk length]; ++index) {
    unichar character = (unichar)bytes[index];
    if ([[NSCharacterSet newlineCharacterSet] characterIsMember:character]) {
      numberOfNewlines++;
    }
  }
  chunk = [file readDataOfLength:chunkSize];
}

Upvotes: 3

Regexident
Regexident

Reputation: 29552

This should get you going:

NSString *fileContents = [NSString stringWithContentsOfFile:file encoding:encoding error:&error];
NSUInteger newlineCount = [fileContents numberOfOccurrencesOfString:@"\n"];

@interface NSString ()

- (NSUInteger)numberOfOccurrencesOfString:(NSString *)aString;
- (NSUInteger)numberOfOccurrencesOfChar:(char)aChar;

@end

@implementation NSString ()

- (NSUInteger)numberOfOccurrencesOfString:(NSString *)aString {
    NSRange range = [self rangeOfString:aString];
    NSUInteger length = [self length];
    NSUInteger count = 0;
    while (range.location != NSNotFound) {
        range = [self rangeOfString:aString options:0 range:NSMakeRange(range.location + range.length, length - range.location - range.length)];
        count++;
    }
    return count;
}

- (NSUInteger)numberOfOccurrencesOfChar:(char)aChar {
    const char *cString = [self cStringUsingEncoding:NSUTF8StringEncoding];
    NSUInteger stringLength = strlen(cString);
    NSUInteger count = 0;
    for (int i = 0; i < stringLength; i++) {
        if (cString[i] == aChar) {
            count++;
        }
    }
    return count;
}

@end

While "numberOfOccurrencesOfString:" allocates no additional memory and supports string needles, "numberOfOccurrencesOfChar:" allocates an autoreleased c-string copy of the NSString and searches for a single char. ""

As you were asking for a count of newlines (hence single chars) I figured a quick benchmark might be good for this particular purpose: So I took a test string of length 2486813 containing total of 78312 '\n'. (I basically took a variation of OSX's words file) and… …ran [testString numberOfOccurrencesOfString:@"\n"] 100 times: 19.35s …ran [testString numberOfOccurrencesOfChar:'\n'] 100 times: 6.91s (Setup: 2.2GHz Core 2 Duo MacBook Pro, run on a single thread)

[Edit: small bug fixed; made second snippet into category string method.]

Upvotes: 3

Warren Burton
Warren Burton

Reputation: 17372

You can scan through the string using SubstringWithRange:

Count up the number of times \n appears.

Upvotes: 0

Related Questions