I need to extract some listmode bigEndian Float data from a binary file format. I was originally using the following method and it worked perfectly, but I am having trouble converting this over to Swift 3...
Original: (example of 20 rows with 15 columns of data that start after 300 bytes of header)
let fileData: NSData = NSData(contentsOfFile: fileInfo.path)!
let ptr = UnsafePointer<UInt8>(fileData.bytes)
let byteOffset = 300
for i in 0..<20 {
let byteOffset2 = byteOffset + (i * 15 * 4)
for p in 0..<15 {
let bits = UnsafePointer<Float._BitsType>(ptr + byteOffset2)[p].bigEndian
let f = Float._fromBitPattern(bits)
eventData[p] = f
}
}
New: (after the automated Xcode conversion and some attempted tweaking to remove errors in Xcode)
let fileData: Data = try! Data(contentsOf: URL(fileURLWithPath: fileInfo.path))
let ptr = (fileData as NSData).bytes.bindMemory(to: UInt32.self, capacity: fileData.count)
let byteOffset = 300
for i in 0..<20 {
let byteOffset2 = byteOffset + (i * 15 * 4)
for p in 0..<15 {
let bits = UnsafePointer<UInt32>(ptr + byteOffset2)[p].bigEndian
let f = Float(bitPattern: bits)
eventData[p] = f
}
}
The values generated from the new method are now incorrect... I have been fiddling for quite a while now and I am stumped - any advice would be much appreciated. I found my original method in this question/answer: Swift: extract float from byte data but it seems that Float._BitsType doesn't work in Swift 3. Any advice will be much appreciated...
The problem (if I guess correctly) is that ptr in your attempted
Swift 3 code is a pointer to UInt32 and not to UInt8 as in the
Swift 2 version. Therefore ptr + byteOffset2 advances the pointer
by 4 * byteOffset2 bytes, and that must be considered when computing
the offsets.
Generally you can simplify the access to Data like this:
data.withUnsafeBytes { (ptr: UnsafePointer<UInt32>) in
let uint32Offset = 300/MemoryLayout<UInt32>.stride // 300/4 = 75
for i in 0 ..< 20 {
for p in 0 ..< 15 {
let offset = uint32Offset + i * 15 + p
let u32Value = UInt32(bigEndian: ptr[offset])
let floatValue = Float(bitPattern: u32Value)
// ...
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With