Kri*_*son 6 nsfilehandle swift
我有一个雨燕程序,它读出FileHandle.standardInput(在Objective-C,这将是+[NSFileHandle fileHandleWithStandardInput],当它击中的输入流档案结尾应该终止阅读,但是当我运行它使用终端(在MacOS塞拉利昂)作为输入,当我按 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)
}
Run Code Online (Sandbox Code Playgroud)
我希望在到达文件末尾时readData(ofLength:)返回一个为零的Data对象count。
当我使用重定向到标准输入的文件运行时,如下所示:
./echo.swift < foo.txt
Run Code Online (Sandbox Code Playgroud)
它写出文件并终止。
但是,如果我像这样运行它:
./echo.swift
Run Code Online (Sandbox Code Playgroud)
然后键入一些文本并按 Ctrl+D,我希望它将 Ctrl+D 视为文件结尾并终止。但它不会那样做。它只是不断地运行和呼应线条。如果我一遍又一遍地按 Ctrl+D,它最终会终止,但这不是我想要的。
改变bufferSize似乎没有帮助。如果我将其设置为1.
我怀疑我需要在stdin文件描述符或终端设备上设置某种缓冲参数,或者捕获信号或其他东西,但我不知道是什么。
我知道我可以改用 C stdio fread()API,它可以从终端正确检测文件结束条件,或者我可以使用 SwiftreadLine(_:)从标准输入中读取,而不必担心文件句柄/描述符,但我想知道是否有一种方法可以使用FileHandle原始文件描述符或原始文件描述符来执行此操作,而无需重新实现 C stdio。
更新:在花了一个小时查看 Apple 的LibC 源代码后,我得出结论“它很复杂”,所以现在我只是fread(..., stdin)在我的程序中使用。但我仍然想知道是否有一些简单的方法可以让它与FileHandle.
小智 2
今天,Swift 5,类似这样的东西......
while (FileHandle.standardInput.availableData.count > 0) {
FileHandle.standardOutput.write(FileHandle.standardInput.availableData)
}
Run Code Online (Sandbox Code Playgroud)
简单,而且工作起来几乎就像一个猫程序,需要一些东西来调整。
正确的行为会更好:
var data: Data
repeat {
data = FileHandle.standardInput.availableData
FileHandle.standardOutput.write(data)
} while (data.count > 0)
Run Code Online (Sandbox Code Playgroud)
关于它的文档:
当前通过接收器可用的数据,最大大小可以由 NSData 对象表示。
如果接收者是文件,该方法返回从当前文件指针到文件末尾读取文件得到的数据。如果接收方是通信通道,则此方法读取数据缓冲区并将其返回;如果没有可用数据,该方法将阻塞。如果到达文件末尾,则返回空数据对象。如果尝试确定文件句柄类型失败或者尝试从文件或通道读取失败,此方法将引发 NSFileHandleOperationException