我如何判断 FileHandle 什么时候没有可读的内容?
How can I tell when a FileHandle has nothing left to be read?
我正在尝试使用 Pipe
's fileHandleForReading
's readabilityHandler
to read both the standardOutput
and standardError
of a Process
. However, the moment the terminationHandler
实际上是在 之前 我的 readabilityHandler
第一次被调用的那一刻。
我不确定进程为什么这样做,但这意味着我没有获得所有数据,因为我假设进程终止意味着所有输出都已刷新到管道。由于情况并非如此,有没有办法告诉我什么时候没有更多的输出要读取? 我假设这涉及检查 FileHandle
是否仍然存在打开,但我没有看到 API。
这是我的代码的基本概念示例:
let stdOutPipe = Pipe()
let stdErrPipe = Pipe()
stdOutPipe.fileHandleForReading.readabilityHandler = { stdOutFileHandle in
let stdOutPartialData = stdOutFileHandle.readDataToEndOfFile()
guard !stdOutPartialData.isEmpty else {
print("Time to read, but nothing to be read?") // happens a lot
return
}
self.tempStdOutStorage.append(stdOutPartialData)
}
stdErrPipe.fileHandleForReading.readabilityHandler = { stdErrFileHandle in
let stdErrPartialData = stdErrFileHandle.readDataToEndOfFile()
guard !stdErrPartialData.isEmpty else {
print("Time to read, but nothing to be read?") // happens a lot
return
}
self.tempStdErrStorage.append(stdErrPartialData)
}
process.standardOutput = stdOutPipe
process.standardError = stdErrPipe
process.terminationHandler = { process in
notifyOfCompleteRead(stdOut: self.tempStdOutStorage, stdErr: self.tempStdErrStorage)
}
mySpecializedDispatchQueue.async(execute: process.launch)
在 readabilityHandler
你应该使用 availableData
来获得
当前可用的数据没有阻塞。空的可用数据表示 EOF
在文件句柄上,在这种情况下,应删除可读性处理程序。
进程完成后,可以使用分派组在标准输出和标准错误上等待 EOF。
示例:
let group = DispatchGroup()
group.enter()
stdOutPipe.fileHandleForReading.readabilityHandler = { stdOutFileHandle in
let stdOutPartialData = stdOutFileHandle.availableData
if stdOutPartialData.isEmpty {
print("EOF on stdin")
stdOutPipe.fileHandleForReading.readabilityHandler = nil
group.leave()
} else {
tempStdOutStorage.append(stdOutPartialData)
}
}
group.enter()
stdErrPipe.fileHandleForReading.readabilityHandler = { stdErrFileHandle in
let stdErrPartialData = stdErrFileHandle.availableData
if stdErrPartialData.isEmpty {
print("EOF on stderr")
stdErrPipe.fileHandleForReading.readabilityHandler = nil
group.leave()
} else {
tempStdErrStorage.append(stdErrPartialData)
}
}
process.standardOutput = stdOutPipe
process.standardError = stdErrPipe
process.launch()
process.terminationHandler = { process in
group.wait()
print("OUTPUT:", String(data: tempStdOutStorage, encoding: .utf8)!)
print("ERROR: ", String(data: tempStdErrStorage, encoding: .utf8)!)
}
我正在尝试使用 Pipe
's fileHandleForReading
's readabilityHandler
to read both the standardOutput
and standardError
of a Process
. However, the moment the terminationHandler
实际上是在 之前 我的 readabilityHandler
第一次被调用的那一刻。
我不确定进程为什么这样做,但这意味着我没有获得所有数据,因为我假设进程终止意味着所有输出都已刷新到管道。由于情况并非如此,有没有办法告诉我什么时候没有更多的输出要读取? 我假设这涉及检查 FileHandle
是否仍然存在打开,但我没有看到 API。
这是我的代码的基本概念示例:
let stdOutPipe = Pipe()
let stdErrPipe = Pipe()
stdOutPipe.fileHandleForReading.readabilityHandler = { stdOutFileHandle in
let stdOutPartialData = stdOutFileHandle.readDataToEndOfFile()
guard !stdOutPartialData.isEmpty else {
print("Time to read, but nothing to be read?") // happens a lot
return
}
self.tempStdOutStorage.append(stdOutPartialData)
}
stdErrPipe.fileHandleForReading.readabilityHandler = { stdErrFileHandle in
let stdErrPartialData = stdErrFileHandle.readDataToEndOfFile()
guard !stdErrPartialData.isEmpty else {
print("Time to read, but nothing to be read?") // happens a lot
return
}
self.tempStdErrStorage.append(stdErrPartialData)
}
process.standardOutput = stdOutPipe
process.standardError = stdErrPipe
process.terminationHandler = { process in
notifyOfCompleteRead(stdOut: self.tempStdOutStorage, stdErr: self.tempStdErrStorage)
}
mySpecializedDispatchQueue.async(execute: process.launch)
在 readabilityHandler
你应该使用 availableData
来获得
当前可用的数据没有阻塞。空的可用数据表示 EOF
在文件句柄上,在这种情况下,应删除可读性处理程序。
进程完成后,可以使用分派组在标准输出和标准错误上等待 EOF。
示例:
let group = DispatchGroup()
group.enter()
stdOutPipe.fileHandleForReading.readabilityHandler = { stdOutFileHandle in
let stdOutPartialData = stdOutFileHandle.availableData
if stdOutPartialData.isEmpty {
print("EOF on stdin")
stdOutPipe.fileHandleForReading.readabilityHandler = nil
group.leave()
} else {
tempStdOutStorage.append(stdOutPartialData)
}
}
group.enter()
stdErrPipe.fileHandleForReading.readabilityHandler = { stdErrFileHandle in
let stdErrPartialData = stdErrFileHandle.availableData
if stdErrPartialData.isEmpty {
print("EOF on stderr")
stdErrPipe.fileHandleForReading.readabilityHandler = nil
group.leave()
} else {
tempStdErrStorage.append(stdErrPartialData)
}
}
process.standardOutput = stdOutPipe
process.standardError = stdErrPipe
process.launch()
process.terminationHandler = { process in
group.wait()
print("OUTPUT:", String(data: tempStdOutStorage, encoding: .utf8)!)
print("ERROR: ", String(data: tempStdErrStorage, encoding: .utf8)!)
}