swift - 我如何判断 FileHandle 什么时候没有可读的内容?

标签 swift cocoa nstask nsfilehandle nspipe

我正在尝试使用 PipefileHandleForReadingreadabilityHandler阅读 standardOutputstandardErrorProcess .然而,此刻 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)!)
}

关于swift - 我如何判断 FileHandle 什么时候没有可读的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52335435/

相关文章:

ios - 如何使用 Swift 模糊 UIImageView 中的现有图像?

swift - 如何在 Swift 中从 Error 转换为 CFError?

iphone - 如何从 UIWebView 获取最后的 HTTP 状态代码?

objective-c - NSView 与 CAgradientlayer

cocoa - 让 NSTask 和 SMJobSubmit 正常运行的问题

ios - GPUImage 和 GPUImageView : App terminated due to memory error

ios - 纵向 View 在 swift 中提供与横向模式相同的宽度

objective-c - 将转换应用于 NSBitmapImageRep

cocoa - NSTask 输出格式

swift - 如果存在管道,则通过 NSTask 的 cURL 不会终止