Last active
May 20, 2016 15:07
-
-
Save gazolla/4500ebce95a18a9a2c79 to your computer and use it in GitHub Desktop.
The following Swift code was created by Martin R. (http://stackoverflow.com/users/1187415/martin-r) and it should be used to read files line-by-line as explained in http://stackoverflow.com/questions/24581517/read-a-file-url-line-by-line-in-swift
This file contains hidden or 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 StreamReader { | |
let encoding : UInt | |
let chunkSize : Int | |
var fileHandle : NSFileHandle! | |
let buffer : NSMutableData! | |
let delimData : NSData! | |
var atEof : Bool = false | |
init?(path: String, delimiter: String = "\n", encoding : UInt = NSUTF8StringEncoding, chunkSize : Int = 4096) { | |
self.chunkSize = chunkSize | |
self.encoding = encoding | |
if let fileHandle = NSFileHandle(forReadingAtPath: path) { | |
self.fileHandle = fileHandle | |
} else { | |
return nil | |
} | |
// Create NSData object containing the line delimiter: | |
if let delimData = delimiter.dataUsingEncoding(NSUTF8StringEncoding) { | |
self.delimData = delimData | |
} else { | |
return nil | |
} | |
if let buffer = NSMutableData(capacity: chunkSize) { | |
self.buffer = buffer | |
} else { | |
return nil | |
} | |
} | |
deinit { | |
self.close() | |
} | |
/// Return next line, or nil on EOF. | |
func nextLine() -> String? { | |
if atEof { | |
return nil | |
} | |
// Read data chunks from file until a line delimiter is found: | |
var range = buffer.rangeOfData(delimData, options: nil, range: NSMakeRange(0, buffer.length)) | |
while range.location == NSNotFound { | |
var tmpData = fileHandle.readDataOfLength(chunkSize) | |
if tmpData.length == 0 { | |
// EOF or read error. | |
atEof = true | |
if buffer.length > 0 { | |
// Buffer contains last line in file (not terminated by delimiter). | |
let line = NSString(data: buffer, encoding: encoding); | |
buffer.length = 0 | |
return line | |
} | |
// No more lines. | |
return nil | |
} | |
buffer.appendData(tmpData) | |
range = buffer.rangeOfData(delimData, options: nil, range: NSMakeRange(0, buffer.length)) | |
} | |
// Convert complete line (excluding the delimiter) to a string: | |
let line = NSString(data: buffer.subdataWithRange(NSMakeRange(0, range.location)), | |
encoding: encoding) | |
// Remove line (and the delimiter) from the buffer: | |
buffer.replaceBytesInRange(NSMakeRange(0, range.location + range.length), withBytes: nil, length: 0) | |
return line | |
} | |
/// Start reading from the beginning of file. | |
func rewind() -> Void { | |
fileHandle.seekToFileOffset(0) | |
buffer.length = 0 | |
atEof = false | |
} | |
/// Close the underlying file. No reading must be done after calling this method. | |
func close() -> Void { | |
if fileHandle != nil { | |
fileHandle.closeFile() | |
fileHandle = nil | |
} | |
} | |
} |
This file contains hidden or 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
if let aStreamReader = StreamReader(path: "/path/to/file") { | |
while let line = aStreamReader.nextLine() { | |
println(line) | |
} | |
// You can close the underlying file explicitly. Otherwise it will be | |
// closed when the reader is deallocated. | |
aStreamReader.close() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment