【发布时间】:2014-07-25 08:18:53
【问题描述】:
我正在尝试使用 Xcode 6 和新的 Swift 语言为 OS X 制作命令行工具。如何将输出发送到 stderr?这是用 println 完成的吗?
【问题讨论】:
我正在尝试使用 Xcode 6 和新的 Swift 语言为 OS X 制作命令行工具。如何将输出发送到 stderr?这是用 println 完成的吗?
【问题讨论】:
对于 Swift 4.x:
import Darwin
fputs("hello from libc\n", stderr)
【讨论】:
\n 来刷新,可能不是太理想。
这是一个从 https://gist.github.com/algal/0a9aa5a4115d86d5cc1de7ea6d06bd91 修改的 Swift 3 sn-p。
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)
【讨论】:
errorPrint 方法(命名为debugPrint 方法),以简化这一点:)
可能是更好的方法,但你可以使用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))
【讨论】:
(foo, 2)。
并不是一个单独的答案,而是在 Rob Napier 的答案之上构建,我们可以创建一个类似 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)
编辑:截至 2015 年 8 月 26 日,Xcode 7 Beta 6,您需要 toStream: 参数名称,如下所示:
println("on-stderr", toStream:&mx_stderr)
【讨论】:
func write(string: String) { fputs(string, stderr) } :)
print 在下面使用了 C 的 stdio - 我写了一个函数,使用 funopen 来重定向“正常”stdout,它拦截了 print()也是。
Swift 4,类似于 Ryan 的解决方案,但不是扩展 FileHandle,而是创建了一个新结构,它还允许您创建一个 StdErr 特定类并避免全局。
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)
}
}
使用示例:
do {
try somethingThatMightFail()
} catch let error {
var errStream = StandardErrorOutputStream()
print("\(error)", to: &errStream)
exit(EXIT_FAILURE)
}
【讨论】:
以下是增加复杂性的三种不同方法:
http://ericasadun.com/2015/06/09/swift-2-0-how-to-print/Erica Sadun 的赞美:
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 的稍微不同的方法,请参阅标题为:写入 stdout / stderr 的部分中的:http://crunchybagel.com/building-command-line-tools-with-swift/,但此方法不使用 Swift 的打印库函数。
对于真正疯狂的旅程,请查看 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")
}
【讨论】:
Xcode 11.3+ 和 Swift 5.1+
扩展名:
final class StandardErrorOutputStream: TextOutputStream {
func write(_ string: String) {
FileHandle.standardError.write(Data(string.utf8))
}
}
用法:
var outputStream = StandardErrorOutputStream()
print("Error!", to: &outputStream)
【讨论】:
@RobNapiers 建议解决方案的精简和现代化版本:
"A line of text"
.data(using: .utf8)
.map(FileHandle.standardError.write)
【讨论】: