切片时返回错误索引值的数据类型
Posted
技术标签:
【中文标题】切片时返回错误索引值的数据类型【英文标题】:Data type returning wrong index values when sliced 【发布时间】:2021-07-31 06:04:13 【问题描述】:我正在尝试将一些二进制块解码为各种固定宽度的整数。删减数据格式为5个UInt32,后跟n个Int16。
我收到的每个块都有 1 个 UInt8 的初始字节,说明该有效负载的大小,然后是 244 个字节的实际数据。我的方法是丢弃这个初始字节,并使用以下代码将剩余数据附加到数据缓冲区:
let payload = data.advanced(by: 1)
payloadBuffer.append(payload)
在收到预期的总字节数(由payloadBuffer.count确定)后,我执行crc32检查以确保数据完整性,通过。
到目前为止一切顺利!
但是我注意到,如果我想对 payloadBuffer 进行切片并删除最初的 20 个字节以仅使用与上述索引类似的方法专注于 Int16,那么索引总是会减少 2 个字节。
所以当我使用以下内容时,我似乎失去了初始 Int16 值:
let slicedBuffer = payload.advanced(by: 20)
但是,如果我使用:
let slicedBuffer = payload.advanced(by: 18)
我正确地获得了初始 Int16 值,即使您认为这是前一个 UInt32 的最后两个字节。
我正在使用以下代码对 slicedBuffer 进行解码(通常带有字节偏移):
Int16(littleEndian: trimmedBuffer.withUnsafeBytes( $0.load(as: Int16.self) ))
我尝试过使用下标代替 .advanced(by:) 以及 .subData(in:),但仍然得到相同的结果。我还尝试了不同的方法来解码 Int16,例如以下一些:
let test = payloadBuffer.withUnsafeBytes bytes -> Int16 in
let int: Int16 = bytes.loadFixedWidthInteger(fromByteOffset: 20)
return int
extension UnsafeRawBufferPointer
func loadFixedWidthInteger<T: FixedWidthInteger>(fromByteOffset offset: Int) -> T
var value: T = 0
withUnsafeMutableBytes(of: &value) valuePtr in
valuePtr.copyBytes(from: UnsafeRawBufferPointer(start: self.baseAddress!.advanced(by: offset),
count: MemoryLayout<T>.size))
return value
或者干脆……
Int16(bytes[21]) << 8 | Int16(bytes[20])
我相信这与字节在内存中未对齐的事实有关吗?我已经阅读了许多与未对齐负载相关的论坛帖子(例如1、2),但建议的解决方案似乎都无法解决问题:
Swift Forum - Unaligned Load
Stack Overflow - Creating an aligned array of bytes
虽然我无法弄清楚是什么导致了这种怪癖,但我终其一生都无法解决?如果有人有任何建议,我将非常感激!
【问题讨论】:
试试converting data to hex看看发生了什么 谢谢@Philip!我最终查看了十六进制编辑器,并意识到问题实际上是由于文档不正确造成的。 【参考方案1】:所以看起来这最终只是数据文档的问题。
【讨论】:
以上是关于切片时返回错误索引值的数据类型的主要内容,如果未能解决你的问题,请参考以下文章
当尝试对 pandas 数据帧进行切片时,它会引发“ValueError('Lengths must match to compare')”