使用 OutputStream 将 CircularBuffer (swift-nio) 写入 Swift 中的文件?
Write a CircularBuffer (swift-nio) to a file in Swift using OutputStream?
我正在尝试使用 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 [=12=].withMemoryRebound(to: UInt8.self, capacity: capacity) {
return Array(UnsafeBufferPointer(start: [=12=], count: capacity))
}
}
}
}
有什么想法吗?
CircularBuffer
是一个带有内部 ContiguousArray
元素存储的结构。 ContiguousArray
也是一个结构,具有指向实际元素存储的内部指针。
您当前的代码会产生垃圾,因为它 returns struct CircularBuffer
本身的内存表示,而不是它所表示的元素的字节。
作为一个集合,CircularBuffer
有一个 withContiguousStorageIfAvailable()
方法,它调用一个带有指向元素存储的指针的闭包 如果存在这样的连续存储。使用 UnsafeBufferPointer
参数调用闭包,您可以从中获得 baseAddress
:
var buffer: CircularBuffer<UInt8> = ...
let os: OutputStream = ...
// ...
let amountWritten = buffer.withContiguousStorageIfAvailable {
os.write([=10=].baseAddress!, maxLength: [=10=].count)
}
但是有一个问题:CircularBuffer
只是继承了Sequence
的默认实现,而returnsnil
没有调用闭包。这是一个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)
我正在尝试使用 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 [=12=].withMemoryRebound(to: UInt8.self, capacity: capacity) {
return Array(UnsafeBufferPointer(start: [=12=], count: capacity))
}
}
}
}
有什么想法吗?
CircularBuffer
是一个带有内部 ContiguousArray
元素存储的结构。 ContiguousArray
也是一个结构,具有指向实际元素存储的内部指针。
您当前的代码会产生垃圾,因为它 returns struct CircularBuffer
本身的内存表示,而不是它所表示的元素的字节。
作为一个集合,CircularBuffer
有一个 withContiguousStorageIfAvailable()
方法,它调用一个带有指向元素存储的指针的闭包 如果存在这样的连续存储。使用 UnsafeBufferPointer
参数调用闭包,您可以从中获得 baseAddress
:
var buffer: CircularBuffer<UInt8> = ...
let os: OutputStream = ...
// ...
let amountWritten = buffer.withContiguousStorageIfAvailable {
os.write([=10=].baseAddress!, maxLength: [=10=].count)
}
但是有一个问题:CircularBuffer
只是继承了Sequence
的默认实现,而returnsnil
没有调用闭包。这是一个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)