3

我想使用调度 IO 通道从文件描述符中读取一些数据。创建通道后,下一步是调用read,其声明如下:

func read(offset: off_t, 
   length: Int, 
    queue: DispatchQueue, 
ioHandler: @escaping (Bool, DispatchData?, Int32) -> Void)

length参数的文档说:

从通道读取的字节数。指定 SIZE_MAX 以继续读取数据,直到达到 EOF。

似乎很容易。就我而言,我只想这样做——读到 EOF。所以我会通过SIZE_MAX

// `queue` and `handler` defined elsewhere
channel.read(offset: 0, length: SIZE_MAX, queue: queue, ioHandler: handler)

精明的读者已经猜到编译器不喜欢这样:

无法将“UInt”类型的值转换为预期的参数类型“Int”

SIZE_MAX是类型UInt,但是length是类型Int。编译器提供修复它:

channel.read(offset: 0, length: Int(SIZE_MAX), queue: queue, ioHandler: handler)

但是,当然,在运行时,效果并不好:

致命错误:没有足够的位来表示有符号值

自然如果SIZE_MAX是 可以表示的最大值UInt,则Int不能表示。经过快速搜索,我在 Swift bug tracker 上找到了这个确切的问题。由于它似乎还没有得到解决——而且我不确定自己是否有能力通过拉取请求来解决它——我该如何解决这个问题?还是我错过了做我想做的事的方法?


Swift Stdlib 基本原理文档涵盖了导入size_tasInt而不是UInt. 它归结为“更少的类型转换,并且无论如何谁需要指定高于 2^63 的数字(对不起,32 位平台)。” 很公平,但这并不包括像我这样的问题,其中使用SIZE_MAX是 API 的一部分。

4

1 回答 1

2

只需使用如果您在 64 位平台上,您仍然几乎可以保证在读取字节Int.max之前到达文件末尾。Int.max在 32 位平台上,如果您的文件非常大,您可能需要发出多个读取。

然后你应该向 Apple 报告这个问题。我不确定 Dispatch IO 库是属于 Apple 还是属于 Swift Open Source 项目,或者它只是一个文档错误。

更新

源代码是开源的,读取操作只是对一个 C 函数的简单包装,该函数需要一个size_tfor 长度。

https://github.com/apple/swift-corelibs-libdispatch/blob/master/src/swift/IO.swift

我还没有尝试过,但您几乎可以肯定使用位模式,甚至可能使用-1. 我想我还是会去Int.max

于 2017-09-25T08:54:10.083 回答