【问题标题】:How to detect end-of-file for FileHandle.standardInput from Terminal如何从终端检测 FileHandle.standardInput 的文件结尾
【发布时间】: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


【解决方案1】:

今天,Swift 5,类似这样的......

while (FileHandle.standardInput.availableData.count > 0) {
  FileHandle.standardOutput.write(FileHandle.standardInput.availableData)
}

简单,运行起来几乎就像一个猫程序,一些东西可以调整。

正确的行为会更好:

var data: Data
repeat {
  data = FileHandle.standardInput.availableData
  FileHandle.standardOutput.write(data)
} while (data.count > 0)

关于它的文档:

当前可通过接收器获得的数据,不超过 NSData 对象可以表示的最大大小。

如果接收方是文件,则该方法返回从当前文件指针到文件末尾读取文件得到的数据。如果接收方是通信通道,则此方法读取数据缓冲区并将其返回;如果没有可用的数据,该方法将阻塞。如果到达文件末尾,则返回一个空数据对象。如果尝试确定文件句柄类型失败或尝试从文件或通道读取失败,则此方法引发 NSFileHandleOperationException

【讨论】:

猜你喜欢
  • 2020-02-22
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 2010-09-07
  • 2017-02-04
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多