Skip to content

Instantly share code, notes, and snippets.

@clmntcrl
Created May 20, 2015 13:37
Show Gist options
  • Save clmntcrl/d15dfb7d751fc522f4bb to your computer and use it in GitHub Desktop.
Save clmntcrl/d15dfb7d751fc522f4bb to your computer and use it in GitHub Desktop.
Generator for reading file line by line.
// FileLineStream by Clément Cyril - @clmntcrl - http://clmntcrl.io/
// Copyright 2015 Clément Cyril.
import Foundation
final class FileLineStream: GeneratorType {
typealias Element = String
private var fileHandle: NSFileHandle?
private var buffer: NSMutableData?
private let bufferCapacity = 4_096
private var encoding: UInt
init(path: String, encoding fileEncoding: UInt = NSUTF8StringEncoding) {
if let fh = NSFileHandle(forReadingAtPath: path),
b = NSMutableData(capacity: bufferCapacity) {
fileHandle = fh
buffer = b
}
encoding = fileEncoding
}
deinit {
fileHandle?.closeFile()
}
func next() -> Element? {
if let fh = fileHandle,
b = buffer,
delimiter = "\n".dataUsingEncoding(encoding) {
var range = b.rangeOfData(delimiter, options: nil, range: NSMakeRange(0, b.length))
while range.location == NSNotFound {
var data = fh.readDataOfLength(bufferCapacity)
if data.length == 0 {
if b.length > 0 { // Last line isn't derminated by delimiter
return NSString(data: b, encoding: encoding) as String?
}
return nil
}
b.appendData(data)
range = b.rangeOfData(delimiter, options: nil, range: NSMakeRange(0, b.length))
}
let line = NSString(data: b.subdataWithRange(NSMakeRange(0, range.location)), encoding: encoding) as String?
b.replaceBytesInRange(NSMakeRange(0, range.location + range.length), withBytes: nil, length: 0)
return line
}
return nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment