'How can I output to STDERR with Swift?
I'm trying to make a command line tool for OS X with Xcode 6 and the new Swift language. How can I send output to stderr? Is this done with println?
Solution 1:[1]
For Swift 4.x:
import Darwin
fputs("hello from libc\n", stderr)
Solution 2:[2]
Here is a Swift 3 snippet modified from https://gist.github.com/algal/0a9aa5a4115d86d5cc1de7ea6d06bd91.
import Foundation
var standardError = FileHandle.standardError
extension FileHandle: TextOutputStream {
public func write(_ string: String) {
let data = Data(string.utf8)
self.write(data)
}
}
print("I am printed to stderr", to: &standardError)
Solution 3:[3]
May be a better way to do it, but you can use NSFileHandle:
import Foundation
// Create a file handle to work with
let stderr = NSFileHandle.fileHandleWithStandardError()
// Build up a string; whatever you want
let stuff = "something"
let something = "I'm a string with \(stuff) in it\n"
// Write it
stderr.writeData(something.dataUsingEncoding(NSUTF8StringEncoding))
Solution 4:[4]
Not really a separate answer, but building on top of Rob Napier's answer, we can create a stderr like object so that there is not much to change when Apple comes around to providing stderr as an OutputStreamType:
import Foundation
class StandardErrorOutputStream: OutputStreamType {
func write(string: String) {
let stderr = NSFileHandle.fileHandleWithStandardError()
stderr.writeData(string.dataUsingEncoding(NSUTF8StringEncoding))
}
}
var mx_stderr = StandardErrorOutputStream()
println("on-stdout")
println("on-stderr", &mx_stderr)
EDIT: As of 8/26/2015, Xcode 7 Beta 6, you need the toStream: parameter name, like so:
println("on-stderr", toStream:&mx_stderr)
Solution 5:[5]
Swift 4, similar to Ryan's solution but instead of extending the FileHandle, created a new struct which also lets you create a StdErr specific class and avoids the global.
struct StandardErrorOutputStream: TextOutputStream {
let stderr = FileHandle.standardError
func write(_ string: String) {
guard let data = string.data(using: .utf8) else {
fatalError() // encoding failure: handle as you wish
}
stderr.write(data)
}
}
Usage example:
do {
try somethingThatMightFail()
} catch let error {
var errStream = StandardErrorOutputStream()
print("\(error)", to: &errStream)
exit(EXIT_FAILURE)
}
Solution 6:[6]
Here are three different methods of increasing complexity:
Compliments of Erica Sadun at http://ericasadun.com/2015/06/09/swift-2-0-how-to-print/:
public struct StderrOutputStream: OutputStreamType {
public mutating func write(string: String) {
fputs(string, stderr)
}
}
public var errStream = StderrOutputStream()
debugPrint("Hello", toStream: &errStream) // prints with new line
For a slightly different method using NSFileHandle.fileHandleWithStandardError, see: http://crunchybagel.com/building-command-line-tools-with-swift/ in the section titled: Writing to stdout / stderr, but this method does not use Swift's print library function.
And for a really crazy ride, check out the method offered by rosettacode.org using NSOutputStream at https://www.rosettacode.org/wiki/Hello_world/Standard_error#Swift:
let out = NSOutputStream(toFileAtPath: "/dev/stderr", append: true)
let err = "Goodbye, World!".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
out?.open()
let success = out?.write(UnsafePointer<UInt8>(err!.bytes), maxLength: err!.length)
out?.close()
if let bytes = success {
print("\nWrote \(bytes) bytes")
}
Solution 7:[7]
Xcode 13.2+ and Swift 5.5+
Model:
class StandardError: TextOutputStream {
func write(_ string: String) {
try! FileHandle.standardError.write(contentsOf: Data(string.utf8))
}
}
Usage:
var standardError = StandardError()
print("Error!", to: &standardError)
Solution 8:[8]
A condensed and modernized version of @RobNapiers suggested solution:
"A line of text"
.data(using: .utf8)
.map(FileHandle.standardError.write)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Keith Smiley |
| Solution 2 | Palle |
| Solution 3 | |
| Solution 4 | Lou Franco |
| Solution 5 | ns. |
| Solution 6 | |
| Solution 7 | ma11hew28 |
| Solution 8 | Era |
