Created
February 14, 2016 20:22
-
-
Save mingsai/e7e559244545a9ba3656 to your computer and use it in GitHub Desktop.
A stream reader delegate class to read a file line by line.
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
// | |
// MNGStreamReader.swift | |
// | |
// | |
// Created by Tommie N. Carter, Jr., MBA on 2/12/16. | |
// Copyright © 2016 MING Technology. All rights reserved. | |
// | |
import Foundation | |
class MNGStreamReader: NSObject, NSStreamDelegate { | |
var callback: ((lineNumber: UInt , stringValue: String) -> ())? | |
var completion: ((Int) -> Void)? | |
var fileURL:NSURL? | |
var inputData:NSData? | |
var inputStream: NSInputStream? | |
var lineNumber:UInt = 0 | |
var queue:NSOperationQueue? | |
var remainder:NSMutableData? | |
var delimiter:NSData? | |
//var reader:NSInputStreamReader? | |
func enumerateLinesWithBlock(block: (UInt, String)->() , completionHandler completion:(numberOfLines:Int) -> Void ) { | |
if self.queue == nil { | |
self.queue = NSOperationQueue() | |
self.queue!.maxConcurrentOperationCount = 1 | |
} | |
assert(self.queue!.maxConcurrentOperationCount == 1, "Queue can't be concurrent.") | |
assert(self.inputStream == nil, "Cannot process multiple input streams in parallel") | |
self.callback = block | |
self.completion = completion | |
if self.fileURL != nil { | |
self.inputStream = NSInputStream(URL: self.fileURL!) | |
} else if self.inputData != nil { | |
self.inputStream = NSInputStream(data: self.inputData!) | |
} | |
self.inputStream!.delegate = self | |
self.inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) | |
self.inputStream!.open() | |
} | |
convenience init? (withData inbound:NSData) { | |
self.init() | |
self.inputData = inbound | |
self.delimiter = "\n".dataUsingEncoding(NSUTF8StringEncoding) | |
} | |
convenience init? (withFileAtURL fileURL: NSURL) { | |
guard !fileURL.fileURL else { return nil } | |
self.init() | |
self.fileURL = fileURL | |
self.delimiter = "\n".dataUsingEncoding(NSUTF8StringEncoding) | |
} | |
@objc func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent){ | |
switch eventCode { | |
case NSStreamEvent.OpenCompleted: | |
fallthrough | |
case NSStreamEvent.EndEncountered: | |
self.emitLineWithData(self.remainder!) | |
self.remainder = nil | |
self.inputStream!.close() | |
self.inputStream = nil | |
self.queue!.addOperationWithBlock({ () -> Void in | |
self.completion!(Int(self.lineNumber) + 1) | |
}) | |
break | |
case NSStreamEvent.ErrorOccurred: | |
NSLog("error") | |
break | |
case NSStreamEvent.HasSpaceAvailable: | |
NSLog("HasSpaceAvailable") | |
break | |
case NSStreamEvent.HasBytesAvailable: | |
NSLog("HasBytesAvaible") | |
if let buffer = NSMutableData(capacity: 4096) { | |
let length = self.inputStream!.read(UnsafeMutablePointer<UInt8>(buffer.mutableBytes), maxLength: buffer.length) | |
if 0 < length { | |
buffer.length = length | |
self.queue!.addOperationWithBlock({ [weak self] () -> Void in | |
self!.processDataChunk(buffer) | |
}) | |
} | |
} | |
break | |
default: | |
break | |
} | |
} | |
func processDataChunk(buffer: NSMutableData) { | |
if self.remainder != nil { | |
self.remainder!.appendData(buffer) | |
} else { | |
self.remainder = buffer | |
} | |
self.remainder!.mng_enumerateComponentsSeparatedBy(self.delimiter!, block: {( component: NSData, last: Bool) in | |
if !last { | |
self.emitLineWithData(component) | |
} | |
else { | |
if 0 < component.length { | |
self.remainder = (component.mutableCopy() as! NSMutableData) | |
} | |
else { | |
self.remainder = nil | |
} | |
} | |
}) | |
} | |
func emitLineWithData(data: NSData) { | |
let lineNumber = self.lineNumber | |
self.lineNumber = lineNumber + 1 | |
if 0 < data.length { | |
if let line = NSString(data: data, encoding: NSUTF8StringEncoding) { | |
callback!(lineNumber: lineNumber, stringValue: line as String) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment