Подтвердить что ты не робот

Как я могу вывести на STDERR с помощью Swift?

Я пытаюсь сделать инструмент командной строки для OS X с Xcode 6 и новым языком Swift. Как отправить вывод на stderr? Это делается с помощью println?

4b9b3361

Ответ 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)
}