【发布时间】:2015-12-06 10:11:00
【问题描述】:
如何在 Swift for Linux 中从标准输入读取用户输入或字符流?
【问题讨论】:
-
我认为
readLine( swiftdoc.org/v2.1/func/readLine ) 应该可以工作,但未在 Linux 上测试 -
它会读到换行,不是吗?
如何在 Swift for Linux 中从标准输入读取用户输入或字符流?
【问题讨论】:
readLine ( swiftdoc.org/v2.1/func/readLine ) 应该可以工作,但未在 Linux 上测试
readLine() 适用于 Ubuntu 15:
[Readline] 返回
Characters 从标准输入读取到结束 当前行或直到到达 EOF,或nil如果 EOF 已经 到达。
例子:
print("\nEnter your name:\n")
if let name = readLine() {
print("\nHello \(name)!\n")
}
ed@swiftux:~/Swift/Scripts$ ./testReadline
输入你的名字:
埃里克
你好埃里克!
readline() 也适用于|(管道):
ed@swiftux:~/Swift/Scripts$ echo "Mike" | ./testReadline
输入你的名字:
你好迈克!
我也尝试过NSFileHandle 的经典方式,但还没有实现:
致命错误:availableData 尚未实现:文件 Foundation/NSObjCRuntime.swift
【讨论】:
如果您在 Linux 上导入 Glibc,在 macOS 上导入 Darwin.C,那么您可以使用 getline 函数一次读取一行。
这需要一点 c 互操作,但您可以将其包装起来以呈现更 Swifty 的界面。例如,以下函数返回一个生成器,该生成器迭代从文件流中读取的行:
#if os(Linux)
import Glibc
#else
import Darwin.C
#endif
func lineGenerator(file:UnsafeMutablePointer<FILE>) -> AnyIterator<String>
{
return AnyIterator { () -> String? in
var line:UnsafeMutablePointer<CChar>? = nil
var linecap:Int = 0
defer { free(line) }
let charactersWritten = getline(&line, &linecap, file)
if charactersWritten > 0 {
guard let line = line else { return nil }
return String(validatingUTF8: line)
}
else {
return nil
}
}
}
这适用于 Swift 3。您可以找到一个小的 swiftecho example project,它可以从命令行执行此操作。
【讨论】:
我找到了一种从stdin 读取字符的方法,但它并不漂亮,但它显示了Glibc 可以做什么。
import Glibc
var buf = UnsafeMutablePointer<CChar>.alloc(32)
fread(buf, 1, 32, stdin)
// or
fgets(buf, 32, stdin)
并且buf 具有输入字符。
【讨论】: