【发布时间】:2017-03-03 02:02:35
【问题描述】:
我有一个从 FileHandle.standardInput 读取的 Swift 程序(在 Objective-C 中,这将是 +[NSFileHandle fileHandleWithStandardInput]。当它到达输入流上的文件结尾时它应该终止读取,但是当我使用它运行它时终端(在 macOS Sierra 上)作为输入,当我按下 Ctrl+D 时它不会检测到文件结尾。
这是我正在做的一个简化示例。这个程序只是从标准输入中读取数据并将它读取的内容写入标准输出:
#!/usr/bin/swift
import Foundation
let input = FileHandle.standardInput
let output = FileHandle.standardOutput
let bufferSize = 1024
var data = input.readData(ofLength: bufferSize)
while data.count > 0 {
output.write(data)
data = output.readData(ofLength: bufferSize)
}
我希望readData(ofLength:) 在到达文件结尾时返回一个count 为零的Data 对象。
当我使用重定向到标准输入的文件运行时,如下所示:
./echo.swift < foo.txt
它写出文件并终止。
但是,如果我这样运行它:
./echo.swift
然后键入一些文本并按 Ctrl+D,我希望它会将 Ctrl+D 视为文件结尾并终止。但它不会那样做。它只是保持运行和回声线。如果我一遍又一遍地按 Ctrl+D,它最终会终止,但这不是我想要的。
更改bufferSize 似乎没有帮助。如果我将其设置为 1,我会得到相同的行为。
我怀疑我需要在stdin 文件描述符或终端设备上设置某种缓冲参数,或捕获信号或其他东西,但我不知道是什么。
我知道我可以改用 C stdio fread() API,它可以正确检测来自终端的文件结束条件,或者我可以使用 Swift 的 readLine(_:) 从标准输入读取而不用担心文件句柄/descriptors,但我想知道是否有办法使用FileHandle 或原始文件描述符而不重新实现 C stdio。
更新:花了一个小时查看 Apple 的 LibC source 后,我得出结论“这很复杂”,所以现在我只在我的程序中使用 fread(..., stdin)。但我仍然想知道是否有一些简单的方法可以使其与FileHandle 一起使用。
【问题讨论】:
-
查看
readLine函数。 -
@rmaddy 谢谢,但我想弄清楚如何使用 NSFileHandle 来做到这一点。我已经更新了问题以澄清这一点。
标签: swift nsfilehandle