【问题标题】:How can I output to STDERR with Swift?如何使用 Swift 输出到 STDERR?
【发布时间】:2014-07-25 08:18:53
【问题描述】:

我正在尝试使用 Xcode 6 和新的 Swift 语言为 OS X 制作命令行工具。如何将输出发送到 stderr?这是用 println 完成的吗?

【问题讨论】:

    标签: macos swift


    【解决方案1】:

    对于 Swift 4.x:

    import Darwin
    fputs("hello from libc\n", stderr)
    

    【讨论】:

    • 这需要一个尾随 \n 来刷新,可能不是太理想。
    【解决方案2】:

    这是一个从 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)
    

    【讨论】:

    • 这是一个很棒的 Swifty 解决方案!我还添加了一个新的全局errorPrint 方法(命名为debugPrint 方法),以简化这一点:)
    • 这绝对是最好的解决方案,因为它适用于任何文件句柄。
    【解决方案3】:

    可能是更好的方法,但你可以使用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))
    

    【讨论】:

    • 是的,似乎应该有一个更简单的方法来做到这一点。 Python 和 C 都有更简单的方法来做到这一点。我发现 Swift 也不会。如果没有更好的结果,我会将其标记为正确答案。
    • 这并没有让我感到震惊。除了这个,Cocoa 也没有办法做到这一点。只有一种 C 方式(标准输出),它不是 Cocoa。 Apple 绝对将 Swift 的重点放在“应用程序”问题上,而不是命令行问题上。 (我也在命令行上做了很多工作......)
    • 这对你有用吗? println("foo", STDERR_FILENO)
    • @GeneDeLisa 打印出(foo, 2)
    【解决方案4】:

    并不是一个单独的答案,而是在 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) } :)
    • 我很惊讶地发现 Swift 的 print 在下面使用了 C 的 stdio - 我写了一个函数,使用 funopen 来重定向“正常”stdout,它拦截了 print()也是。
    【解决方案5】:

    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)
    }
    

    【讨论】:

      【解决方案6】:

      以下是增加复杂性的三种不同方法:

      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")
      }
      

      【讨论】:

        【解决方案7】:

        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)
        

        【讨论】:

          【解决方案8】:

          @RobNapiers 建议解决方案的精简和现代化版本:

          "A line of text"
              .data(using: .utf8)
              .map(FileHandle.standardError.write)
          

          【讨论】:

            猜你喜欢
            • 2011-02-28
            • 1970-01-01
            • 2021-02-04
            • 1970-01-01
            • 2019-09-04
            • 2017-06-25
            • 2010-09-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多