使用OutputStream在Swift中的文件中写入CircularBufferswift-nio吗?

问题描述

我正在尝试使用SwiftNIO中的CircularBuffer<UInt8>存储数据,一旦缓冲区快满了,就使用OutputStream内容转储到文件中。不幸的是,OutputStream.write()方法使用UnsafePointer作为参数,而CircularBuffer可以输出UnsafeBufferPointer。是否可以将CircularBuffer转换为UnsafePointer

我已经尝试使用以下代码扩展CircularBuffer,并将其成功地用于将结构转换为字节数组,因为有人建议CircularBuffer实际上是一个结构,但是我的输出文件中出现了垃圾

extension CircularBuffer {
    func toBytes() -> [UInt8] {
        let capacity = MemoryLayout<Self>.size
        var mutableValue = self
        return withUnsafePointer(to: &mutableValue) {
            return $0.withMemoryRebound(to: UInt8.self,capacity: capacity) {
                return Array(UnsafeBufferPointer(start: $0,count: capacity))
            }
        }
    }
}

有什么想法吗?

解决方法

CircularBuffer是具有内部ContiguousArray用于元素存储的结构。 ContiguousArray也是一个结构,带有指向实际元素存储的内部指针。

您当前的代码会产生垃圾,因为它返回struct CircularBuffer本身的内存表示形式,而不是它表示的元素的字节。

作为集合,CircularBuffer有一个withContiguousStorageIfAvailable()方法,如果存在这种连续存储,它会使用指向元素存储的指针来调用闭包。 UnsafeBufferPointer个自变量,您可以从中获取baseAddress

var buffer: CircularBuffer<UInt8> = ...
let os: OutputStream = ...
// ...
let amountWritten =  buffer.withContiguousStorageIfAvailable {
    os.write($0.baseAddress!,maxLength: $0.count)
}

但是有一个问题:CircularBuffer仅继承了Sequence的默认实现,该默认实现返回nil而不调用闭包。这是known issue。因此上面的代码可以编译,但是不起作用。

一种简单的方法(以复制内容为代价)是使用可以从集合中初始化数组的方法:

var buffer: CircularBuffer<UInt8> = ...
let os: OutputStream = ...
// ...
let contents = Array(buffer)
let amountWritten = os.write(contents,maxLength: contents.count)
,

您也可以一次循环浏览缓冲区的各个元素,尽管这可能效率很低:

    var cb = CircularBuffer<UInt8>()
    cb.append(contentsOf:[1,2,3])
    cb.append(contentsOf:[4,5,6])
    let stream = OutputStream.toMemory()
    stream.open()
    for var i in cb {
        stream.write(&i,maxLength:1)
        print(i)
    }
    stream.close()
    print(stream.property(forKey: .dataWrittenToMemoryStreamKey) as Any)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...