Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sakiwei/66511c16f7ecec3eef78bd8f346bfe8c to your computer and use it in GitHub Desktop.
Save sakiwei/66511c16f7ecec3eef78bd8f346bfe8c to your computer and use it in GitHub Desktop.
class FileReader {
// 1.
private let fileHanlde: NSFileHandle
private let lineDelimiter = "\n"
private let chunkSize: Int = 16
private let totalFileLen: UInt64
private var currentOffset: UInt64 = 0
// 2.
init?(path: String) {
guard let fh = NSFileHandle(forReadingAtPath: path) else { return nil }
fileHanlde = fh
fileHanlde.seekToEndOfFile()
totalFileLen = fileHanlde.offsetInFile
}
// 3.
deinit {
fileHanlde.closeFile()
}
func readLine() -> String? {
// 4.
guard let newLineData = lineDelimiter.dataUsingEncoding(NSUTF8StringEncoding) where currentOffset < totalFileLen else { return nil }
fileHanlde.seekToFileOffset(currentOffset)
let currentData = NSMutableData()
var shouldReadMore = true
// 5.
autoreleasepool {
while (shouldReadMore) {
if currentOffset >= totalFileLen {
break;
}
var chunk = fileHanlde.readDataOfLength(chunkSize);
let newLineRange = chunk.rangeOfData_dd(newLineData)
if newLineRange.location != NSNotFound {
// include the length so we can include the delimiter in the string
chunk = chunk.subdataWithRange(NSMakeRange(0, newLineRange.location + newLineData.length))
shouldReadMore = false
}
currentData.appendData(chunk)
currentOffset += UInt64(chunk.length)
}
}
return NSString(data: currentData, encoding: NSUTF8StringEncoding) as? String
}
func readTrimmedLine() -> String? {
return self.readLine()?.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
// 6.
func enumerateLines(callback: (String) -> Bool) {
var stop = false
while !stop {
if let l = self.readLine() {
// if returns false from callback, the loop will exit
stop = !callback(l)
} else {
break;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment