开发者

Count number of newlines in a file

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

Thanks!


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];
}


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.]


You can scan through the string using SubstringWithRange:

Count up the number of times \n appears.


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)


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;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜