Skip to content

Instantly share code, notes, and snippets.

@eienf
Created January 7, 2018 13:44
Show Gist options
  • Save eienf/6c50dada3d0cdea3e869aa75bbd4d545 to your computer and use it in GitHub Desktop.
Save eienf/6c50dada3d0cdea3e869aa75bbd4d545 to your computer and use it in GitHub Desktop.
Read large text file line by line. Swift 2 version.
import Foundation
class StreamReader {
let encoding: NSStringEncoding
let chunkSize: Int
let fileHandle: NSFileHandle
var buffer: NSMutableData
let delimPattern : NSData
var isAtEOF: Bool = false
init?(_ handle: NSFileHandle, delimeter: String = "\n", encoding: NSStringEncoding = NSUTF8StringEncoding, chunkSize: Int = 4096)
{
self.fileHandle = handle
self.chunkSize = chunkSize
self.encoding = encoding
self.buffer = NSMutableData(capacity: chunkSize)!
self.delimPattern = delimeter.dataUsingEncoding(NSUTF8StringEncoding)!
}
deinit {
fileHandle.closeFile()
}
func rewind() {
fileHandle.seekToFileOffset(0)
buffer = NSMutableData(capacity: chunkSize)!
isAtEOF = false
}
func nextLine() -> String? {
if isAtEOF { return nil }
repeat {
let range = buffer.rangeOfData(delimPattern, options: [], range: NSRange(location: 0,length: buffer.length))
if range.location != NSNotFound {
if range.location == 0 {
let remain = NSRange(location: range.length,
length: buffer.length - range.length )
buffer = buffer.subdataWithRange(remain).mutableCopy() as! NSMutableData
continue
}
let datarange = NSRange(location: 0, length: range.location)
let lengthWithDelimiter = range.location + range.length
let subData = buffer.subdataWithRange(datarange)
let line = String(data: subData, encoding: encoding)
let remain = NSRange(location: datarange.location + lengthWithDelimiter,
length: buffer.length - lengthWithDelimiter )
buffer = buffer.subdataWithRange(remain).mutableCopy() as! NSMutableData
return line
} else {
let tempData = fileHandle.readDataOfLength(chunkSize)
if tempData.length == 0 {
isAtEOF = true
return (buffer.length > 0) ? String(data: buffer, encoding: encoding) : nil
}
buffer.appendData(tempData)
}
} while true
}
}
@eienf
Copy link
Author

eienf commented Jan 7, 2018

This is just a damn copy from scooop's original Swift 3 version.

sooop/StreamReader.swift

but use FileHandle instead of URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment