Last active
July 16, 2016 17:27
-
-
Save sakiwei/66511c16f7ecec3eef78bd8f346bfe8c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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