Here is a class that provides all the same syntax and error checking for reading a TextFile. This of course uses the Folderitem class previous posted.
/*
+------------+----------------------------------------------------------------+
| Name | textInputFile [to be consistent with textOutputFile] |
+------------+----------------------------------------------------------------+
| Type | class |
+------------+----------------------------------------------------------------+
| Properties| EOF |
+------------+----------------------------------------------------------------+
| Methods| open readALL readLine |
| | close read |
+------------+----------------------------------------------------------------+
*/
class textInputFile {
private var fileHandle : FileHandle?
private var zIsOpen : Bool = false
private var zEOF : Bool = false
private let delimiter : String = "\n"
private let encoding : UInt = String.Encoding.utf8.rawValue
private let chunkSize : Int = 96//4096
private let buffer : NSMutableData?
private let delimData : NSData?
required init() {
zIsOpen=false
ThrowErrorMessage( .OK )
buffer = NSMutableData(capacity: chunkSize)
delimData = delimiter.data(using: String.Encoding.utf8)! as NSData
}
public var lastErrorCode : Int { get { return zLastErrorCode } }
public var readError : Bool { get {return zLastErrorCode != 0 } }
public var lastErrorMessage : String { get { return zLastErrorMsg } }
public func open(_ f : folderitem ) {
zIsOpen=false
zEOF = false
if f.exists==true {
fileHandle = FileHandle(forReadingAtPath: f.path)!
if fileHandle != nil { zIsOpen=true }
if zIsOpen==false {
ThrowErrorMessage( .BADFILE)
}
}
}
public var EOF : Bool { get { return zEOF } }
public func close() {
if zIsOpen {
fileHandle?.closeFile()
zIsOpen=false
}
}
public var readALL : String { get { return NSString(data:(fileHandle?.readDataToEndOfFile())!, encoding: encoding)! as String } }
// NOTE : this routine returns ONE extra line, as it detects EOF BEFORE the read not after :(
public var readLine : String? { get {
precondition(fileHandle != nil, "Attempt to read from closed file")
if zEOF { return nil }
// Read data chunks from file until a line delimiter is found:
var range = buffer?.range(of: delimData! as Data, options: [], in: NSMakeRange(0, (buffer?.length)!))
while range?.location == NSNotFound {
let tmpData = fileHandle?.readData(ofLength: chunkSize)
if tmpData?.count == 0 {
// EOF or read error.
zEOF = true
if (buffer?.length)! > 0 {
// Buffer contains last line in file (not terminated by delimiter).
let line = NSString(data: buffer! as Data, encoding: encoding)
buffer?.length = 0
return line as String?
}
// No more lines.
return ""//nil
}
buffer?.append(tmpData!)
range = buffer?.range(of: delimData! as Data, options: [], in: NSMakeRange(0, (buffer?.length)!))
}
// Convert complete line (excluding the delimiter) to a string:
let line = NSString(data: (buffer?.subdata(with: NSMakeRange(0, (range?.location)!)))!, encoding: encoding)
// Remove line (and the delimiter) from the buffer:
buffer?.replaceBytes(in: NSMakeRange(0, (range?.location)! + (range?.length)!), withBytes: nil, length: 0)
return line as String?
}
}
}