So the following appears to be a way to open a file for i-o and write to it:
import Foundation
let s = "Test"
let filePath = "filefile.txt"
let u = URL(fileURLWithPath: filePath)
if let d = s.data(using: .utf8) {
do {
let fh1 = try FileHandle(forUpdating: u)
defer { fh1.closeFile() }
print(fh1)
fh1.write(d)
}
catch {
switch error {
case let e as CocoaError:
print("CocoaError: \(e)")
case let e as NSError:
print("NSError: \(e)")
if let reason = e.localizedFailureReason {
print("Reason: \(reason)")
}
print("Domain: \(e.domain)")
print("Code: \(e.code)")
print("User Info: \(e.userInfo)")
default:
print("other error")
}
fatalError("Error opening file")
}
}
else {
print("String conversion failed")
}
At first I only had the catch contain:
catch {
print("Error: \(e)")
fatalError("Error opening file")
}
That only gave me the not terribly useful "Error: The operation could not be completed".
I tried researching using the official Apple documentation and it was less than useful in helping me determine the issue. So I searched the Swift github repository and was able to back myself in to at least seeing it's an "NSError". From there I found the domain, code and userInfo properties. So now I have the above, which gives me:
NSError: The operation could not be completed
Domain: NSCocoaErrorDomain
Code: 4
User Info: ["NSURL": <CFURL 0x60ff10 [0x7ff260dfca98]>{string = filefile.txt, encoding = 134217984
base = <CFURL 0x613de0 [0x7ff260dfca98]>{string = file:///mnt/d/src/swift/, encoding = 134217984, base = (null)}}]
Fatal error: Error opening file: file filehandle.swift, line 29
In the end, looking at FileHandle.swift I see this:
throw _NSErrorWithErrno(errno, reading: reading, url: url)
This leads me to FoundationErrors.swift, where func _NSErrorWithErrno is defined. In the end I find NSError.swift which contains POSIX error codes. It looks like 4 would be EIO, though I'm not really sure on that.
Anyway, this is all a long way of saying that, though I know in the end that the cause of the error is the fact that the file I am trying to open does not in fact exist, if I didn't know that I might have a hell of a time making that determination. Why is this so convoluted? Certainly it should not require me to read the run-time source code to determine the cause of an error... Am I missing something simple?
All of this is on the Windows 10 Ubuntu Linux subsystem, by the way, but I don't think that's particularly relevant.