Я пытаюсь сделать инструмент командной строки для OS X с Xcode 6 и новым языком Swift. Как отправить вывод на stderr? Это делается с помощью println?
Как я могу вывести на STDERR с помощью Swift?
Ответ 1
import Darwin
fputs("hello from libc\n", __stderrp)
Обратите внимание, что stderr не поддерживается в Playgrounds или REPL и будет аварийно завершен в обоих этих местах (начиная с Swift 1.1).
Ответ 2
Возможно, это лучший способ сделать это, но вы можете использовать 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))
Ответ 3
Не совсем отдельный ответ, но на основе ответа Роба Напира мы можем создать объект, похожий на stderr, чтобы не изменилось, когда Apple приходит к обеспечению stderr как 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: по состоянию на 8/26/2015, Xcode 7 Beta 6 вам нужно имя параметра toStream:
, например:
println("on-stderr", toStream:&mx_stderr)
Ответ 4
Вот фрагмент Swift 3
из https://gist.github.com/algal/0a9aa5a4115d86d5cc1de7ea6d06bd91
import Foundation
var standardError = FileHandle.standardError
extension FileHandle : TextOutputStream {
public func write(_ string: String) {
guard let data = string.data(using: .utf8) else { return }
self.write(data)
}
}
print("I am printed to stderr",to:&standardError)
Ответ 5
Вот три разных способа увеличения сложности:
Комплименты Эрика Садун в 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
Для немного другого метода, использующего NSFileHandle.fileHandleWithStandardError, см. http://crunchybagel.com/building-command-line-tools-with-swift/ в разделе под названием: Запись в stdout/stderr, но этот метод не использует библиотечную функцию Swift print.
И для действительно сумасшедшей поездки ознакомьтесь с методом, предлагаемым rosettacode.org, с помощью NSOutputStream на 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")
}
Ответ 6
Swift 4, аналогичный решению Ryan, но вместо расширения FileHandle создал новую структуру, которая также позволяет вам создавать специфический класс StdErr и избегать глобального.
struct StandardErrorOutputStream: TextOutputStream {
let stderr = FileHandle.standardError
func write(_ string: String) {
guard let data = string.data(using: .utf8) else {
return // encoding failure
}
stderr.write(data)
}
}
Пример использования:
do {
try somethingThatMightFail()
} catch let error {
var errStream = StandardErrorOutputStream()
print("\(error)", to: &errStream)
exit(EXIT_FAILURE)
}