Skip to content

Instantly share code, notes, and snippets.

@petershaw
Last active October 29, 2016 07:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petershaw/51db7df73e4bf06bb935a3abb41d8b64 to your computer and use it in GitHub Desktop.
Save petershaw/51db7df73e4bf06bb935a3abb41d8b64 to your computer and use it in GitHub Desktop.
import Foundation
class StreamReader {
let encoding : String.Encoding
let chunkSize : Int
var fileHandle : FileHandle!
let buffer : NSMutableData!
var stored : [Character] = Array()
var stored_idx: Int = 0
var stored_cnt: Int = 0
let delimData : NSData!
var atEof : Bool = false
init?(path: String, delimiter: String = "\n", encoding: String.Encoding = String.Encoding.utf8, chunkSize : Int = 4096) {
self.chunkSize = chunkSize
self.encoding = encoding
if let fileHandle = FileHandle(forReadingAtPath: path),
let delimData = delimiter.data(using: encoding),
let buffer = NSMutableData(capacity: chunkSize)
{
self.fileHandle = fileHandle
self.delimData = delimData as NSData!
self.buffer = buffer
self.stored = Array()
self.stored_idx = 0
} else {
self.fileHandle = nil
self.delimData = nil
self.buffer = nil
self.stored = Array()
self.stored_idx = 0
return nil
}
}
deinit {
self.close()
}
/// Return next character, or nil on EOF.
func nextChar() -> Character? {
//precondition(fileHandle != nil, "Attempt to read from closed file")
if atEof {
return nil
}
if stored_cnt > (stored_idx + 1) {
stored_idx += 1
return stored[stored_idx]
}
let tmpData = fileHandle.readData(ofLength: (chunkSize))
if tmpData.count == 0 {
atEof = true
return nil
}
if let s = NSString(data: tmpData, encoding: encoding.rawValue) as String! {
stored = s.characters.map { $0 }
stored_idx = 0
stored_cnt = stored.count
}
return stored[0];
}
/// Start reading from the beginning of file.
func rewind() -> Void {
fileHandle.seek(toFileOffset: 0)
buffer.length = 0
stored_cnt = 0
atEof = false
}
/// Close the underlying file. No reading must be done after calling this method.
func close() -> Void {
fileHandle?.closeFile()
fileHandle = nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment