在 Swift 中使用 NSInputStream 从 STDIN 获取输入

Get input from STDIN using NSInputStream in Swift

我知道如何使用 NSFileHandle 从 STDIN 读取数据,但我想知道 (1) 是否可以使用 NSInputStream 从 STDIN 读取数据。另外,我在代码下面编写了代码,另一个问题是(2)为什么会抛出异常?好像是inputStream!有可用字节。

#!/usr/bin/env xcrun swift

import Foundation

let inputStream             = NSInputStream(fileAtPath: "/dev/stdin")

inputStream!.open()

println(inputStream!.hasBytesAvailable)

if(inputStream!.hasBytesAvailable) {
  let readBufferRef         = UnsafeMutablePointer<UnsafeMutablePointer<UInt8>>()
  let readBufferLengthRef   = UnsafeMutablePointer<Int>()
  let readBufferIsAvailable = inputStream!.getBuffer(readBufferRef, length: readBufferLengthRef)

  if readBufferIsAvailable {
    println("Yay")
  }
}

println("Heck")


$ printf "%d\n%d\n" 1 2 | ./stdin_stdout_2.swift 
true
0  swift                    0x000000010d410b68 llvm::sys::PrintStackTrace(__sFILE*) + 40
1  swift                    0x000000010d411054 SignalHandler(int) + 452
2  libsystem_platform.dylib 0x00007fff9a7bdf1a _sigtramp + 26
3  libsystem_platform.dylib 0x00007fff534ade70 _sigtramp + 3100573552
4  CoreFoundation           0x00007fff8f59fc17 -[__NSCFInputStream getBuffer:length:] + 23
5  CoreFoundation           0x00000001114c4314 -[__NSCFInputStream getBuffer:length:] + 2180138772
6  swift                    0x000000010ca85c39 llvm::JIT::runFunction(llvm::Function*, std::__1::vector<llvm::GenericValue, std::__1::allocator<llvm::GenericValue> > const&) + 329
7  swift                    0x000000010cd320b3 llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 1523
8  swift                    0x000000010c96e6ba swift::RunImmediately(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, swift::IRGenOptions&, swift::SILOptions const&) + 1066
9  swift                    0x000000010c75764b frontend_main(llvm::ArrayRef<char const*>, char const*, void*) + 5275
10 swift                    0x000000010c754a6d main + 1677
11 libdyld.dylib            0x00007fff98fca5c9 start + 1
12 libdyld.dylib            0x000000000000000d start + 1728272965
Stack dump:
0.  Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret ./stdin_stdout_2.swift -target x86_64-apple-darwin14.1.0 -target-cpu core2 -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk -color-diagnostics -module-name stdin_stdout_2 
Segmentation fault: 11

问题是 readBufferRef 使用 UnsafeMutablePointer<UnsafeMutablePointer<UInt8>>()readBufferLengthRef 使用 UnsafeMutablePointer<Int>()

修改后的代码

#!/usr/bin/env xcrun swift

import Foundation

let inputStream                = NSInputStream(fileAtPath: "/dev/stdin")

inputStream!.open()

println(inputStream!.hasBytesAvailable)

if(inputStream!.hasBytesAvailable) {
  // var readBufferRef         = UnsafeMutablePointer<UnsafeMutablePointer<UInt8>>()
  var readBufferRef            = UnsafeMutablePointer<UInt8>()
  // var readBufferLengthRef   = UnsafeMutablePointer<Int>()
  var readBufferLengthRef      = 0
  // let readBufferIsAvailable = inputStream!.getBuffer(readBufferRef, length: readBufferLengthRef)
  let readBufferIsAvailable    = inputStream!.getBuffer(&readBufferRef, length: &readBufferLengthRef)

  if readBufferIsAvailable {
    println("Yay")
  }
}

println("Heck")