我的应用程序使用了一个在二进制文件中编码的有点复杂的不可变数据结构.我需要在字节级别访问它,避免任何复制.通常,我会使用C或C++指针算法和类型转换来访问和解释原始字节值.我想对Swift做同样的事情.
我发现以下工作:
class RawData {
var data: NSData!
init(rawData: NSData) {
data = rawData
}
func read<T>(byteLocation: Int) -> T {
let bytes = data.subdataWithRange(NSMakeRange(byteLocation, sizeof(T))).bytes
return UnsafePointer<T>(bytes).memory
}
func example_ReadAnIntAtByteLocation5() -> Int {
return read(5) as Int
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我不确定它的效率如何.每次调用它时都要做data.subdataWithRange并NSMakeRange分配对象,或者它们只是处理指针的语法糖?
在Swift中有更好的方法吗?
编辑:
我创建了一个小的Objective-C类,它只封装了一个函数,用于将指针偏移给定的字节数:
@implementation RawDataOffsetPointer
inline void* offsetPointer(void* ptr, int bytes){
return (char*)ptr + bytes;
}
@end
Run Code Online (Sandbox Code Playgroud)
如果我在桥接头中包含此类,那么我可以将我的read方法更改为
func read<T>(byteLocation: Int) -> T {
let ptr = offsetPointer(data.bytes, CInt(byteLocation))
return UnsafePointer<T>(ptr).memory
}
Run Code Online (Sandbox Code Playgroud)
它不会从我的缓冲区复制数据,也不会分配其他对象.
但是,如果可能的话,从Swift做一些指针算法仍然会很好.
rus*_*hop 16
如果你只是想直接做,UnsafePointer<T>可以算术操作:
let oldPointer = UnsafePointer<()>
let newPointer = oldPointer + 10
Run Code Online (Sandbox Code Playgroud)
你也可以像这样抛出一个指针(UnsafePointer<()>相当于void *)
let castPointer = UnsafePointer<MyStruct>(oldPointer)
Run Code Online (Sandbox Code Playgroud)
Eri*_*rik 15
我建议调查NSInputStream,它允许你读取NSData一系列字节(UInt8在Swift中).
这是我在操场上放在一起的一个小样本:
func generateRandomData(count:Int) -> NSData
{
var array = Array<UInt8>(count: count, repeatedValue: 0)
arc4random_buf(&array, UInt(count))
return NSData(bytes: array, length: count)
}
let randomData = generateRandomData(256 * 1024)
let stream = NSInputStream(data: randomData)
stream.open() // IMPORTANT
var readBuffer = Array<UInt8>(count: 16 * 1024, repeatedValue: 0)
var totalBytesRead = 0
while (totalBytesRead < randomData.length)
{
let numberOfBytesRead = stream.read(&readBuffer, maxLength: readBuffer.count)
// Do something with the data
totalBytesRead += numberOfBytesRead
}
Run Code Online (Sandbox Code Playgroud)
您可以创建一个extension读取基元类型,如下所示:
extension NSInputStream
{
func readInt32() -> Int
{
var readBuffer = Array<UInt8>(count:sizeof(Int32), repeatedValue: 0)
var numberOfBytesRead = self.read(&readBuffer, maxLength: readBuffer.count)
return Int(readBuffer[0]) << 24 |
Int(readBuffer[1]) << 16 |
Int(readBuffer[2]) << 8 |
Int(readBuffer[3])
}
}
Run Code Online (Sandbox Code Playgroud)
小智 11
我建议使用UnsafeArray的简单方法.
let data = NSData(contentsOfFile: filename)
let ptr = UnsafePointer<UInt8>(data.bytes)
let bytes = UnsafeBufferPointer<UInt8>(start:ptr, count:data.length)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17558 次 |
| 最近记录: |