[英]How to check for End-of-File using NSFileHandle's readabilityHandler?
I am reading data from a NSFileHandle
(from a NSPipe
) using a readabilityHandler
block:我正在使用
NSPipe
块从NSFileHandle
(来自NSPipe
) readabilityHandler
数据:
fileHandle.readabilityHandler = ^( NSFileHandle *handle ) {
[self processData: [handle availableData]];
}
This works fine, I get all the data I expect fed to my processData
method.这很好用,我得到了我期望输入到我的
processData
方法的所有数据。 The problem is that I need to know when the last chunk of data was read.问题是我需要知道最后一块数据是什么时候读取的。
availableData
should return an empty NSData
instance if it reached end-of-file, but the problem is that the reachability handler is not called again on EOF. availableData
到达文件结尾,则它应该返回一个空的NSData
实例,但问题是在 EOF 上不会再次调用可达性处理程序。
I can't find anything about how to get some kind of notification or callback on EOF.我找不到有关如何在 EOF 上获得某种通知或回调的任何信息。 So what am I missing?
那么我错过了什么? Is Apple really providing an asynchronous reading API without an EOF callback?
苹果真的提供了没有 EOF 回调的异步读取 API 吗?
By the way, I cannot use the runloop based readInBackgroundAndNotify
method since I don't have a runloop available.顺便说一下,我不能使用基于
readInBackgroundAndNotify
方法,因为我没有可用的 runloop。 If I cannot get this to work with the NSFileHandle
API I probably will directly use a dispatch source to do the IO.如果我不能
NSFileHandle
与NSFileHandle
API 一起工作,我可能会直接使用调度源来执行 IO。
I personally compare current file offset with current file position and stop reading.我个人将当前文件偏移量与当前文件位置进行比较并停止阅读。
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
}
}
}
I couldn't understand why it's been designed in this way for a long time, but now I think this could be intentional.很长一段时间我都无法理解为什么它是这样设计的,但现在我认为这可能是故意的。
In my opinion, Apple basically defines FileHandle
as an infinite stream, therefore, EOF is not well defined unless you close the file.在我看来,Apple 基本上将
FileHandle
定义为无限流,因此,除非您关闭文件,否则 EOF 定义不明确。 FileHandle
seem to be more like a "channel". FileHandle
似乎更像是一个“通道”。
It's also unclear what happens if another process appends/delete some data to/from the file while you're reading from it.还不清楚如果另一个进程在您读取文件时向文件中添加/删除一些数据/从文件中删除会发生什么。 What would be the EOF in this case?
在这种情况下,EOF 是什么? As far as I find, there's no mention about this case in Apple documentation.
据我所知,Apple 文档中没有提及此案例。 As far as I know, there's no true exclusive file I/O lock in macOS like other Unix-like systems.
据我所知,macOS 中没有像其他类 Unix 系统那样真正的独占文件 I/O 锁。
In my opinion, availableData
can return empty data at any time if I/O is not fast enough, and readabilityHandler
just don't care about EOF.在我看来,如果 I/O 不够快,
availableData
可以随时返回空数据,而readabilityHandler
只是不关心 EOF。
I believe the accepted answer is actually incorrect.我相信接受的答案实际上是不正确的。 The readabilityHandler is indeed called when EOF is reached.
当达到 EOF 时确实会调用 readabilityHandler。 That is signaled by having availableData be of 0 size.
这是通过使 availableData 的大小为 0 来表示的。
Here's a simple playground that attests to this.这是一个简单的操场证明了这一点。
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
I'm afraid you're out of luck doing this with NSFileHandle
if you can't use readInBackgroundAndNotify
.如果你不能使用
readInBackgroundAndNotify
恐怕你不走运NSFileHandle
这样做。
Two solutions I see:我看到的两种解决方案:
readInBackgroundAndNotify
.readInBackgroundAndNotify
。dispatch_io_*
dispatch_io_*
滚动你自己的实现
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.