我正在使用NSFileHandle
块从NSPipe
(来自readabilityHandler
)读取数据:
fileHandle.readabilityHandler = ^( NSFileHandle *handle ) {
[self processData: [handle availableData]];
}
这很好用,我得到了我期望用于processData
方法的所有数据。问题是我需要知道何时读取了最后一块数据。 availableData
如果到达文件末尾,则应该返回一个空的NSData
实例,但问题是在EOF上不再调用可达性处理程序。
我找不到任何关于如何在EOF上获得某种通知或回调的信息。那我错过了什么? Apple是否真的提供了一个没有EOF回调的异步读取API?
顺便说一下,我不能使用基于runloop的readInBackgroundAndNotify
方法,因为我没有可用的runloop。如果我无法使用NSFileHandle
API,我可能会直接使用调度源来执行IO。
答案 0 :(得分:1)
如果您无法使用NSFileHandle
,我担心如果您使用readInBackgroundAndNotify
,请执行此操作。
我看到两种解决方案:
readInBackgroundAndNotify
。dispatch_io_*
答案 1 :(得分:1)
我相信接受的答案实际上是不正确的。到达EOF时,确实会调用readabilityHandler。这是通过将availableData的大小设置为0来表示的。
这是一个证明这一点的简单游乐场。
import Foundation
import PlaygroundSupport
let pipe = Pipe()
pipe.fileHandleForReading.readabilityHandler = { fh in
let d = fh.availableData
print("Data length: \(d.count)")
if (d.count == 0) {
fh.readabilityHandler = nil
}
}
pipe.fileHandleForWriting.write("Hello".data(using: .utf8)!)
pipe.fileHandleForWriting.closeFile()
PlaygroundPage.current.needsIndefiniteExecution = true
答案 2 :(得分:0)
我个人将当前文件的偏移量与当前文件的位置进行比较,然后停止读取。
extension FileHandle {
func stopReadingIfPassedEOF() {
let pos = offsetInFile
let len = seekToEndOfFile()
if pos < len {
// Resume reading.
seek(toFileOffset: pos)
}
else {
// Stop.
// File offset pointer stays at the EOF.
readabilityHandler = nil
}
}
}
我不明白为什么这么长时间设计它,但是现在我认为这可能是故意的。
我认为,Apple基本上将FileHandle
定义为无限流,因此,除非关闭文件,否则EOF定义不明确。 FileHandle
似乎更像是一个“渠道”。
当您从文件中读取数据时,如果另一个进程向文件中添加/删除一些数据,会发生什么,也不清楚。在这种情况下,EOF是多少?据我所知,Apple文档中没有提及这种情况。据我所知,在macOS中没有像其他类似Unix的系统那样真正的排他文件I / O锁定。
我认为,如果I / O不够快,availableData
可以随时返回空数据,而readabilityHandler
只是在乎EOF。