切片时返回错误索引值的数据类型

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】:

所以看起来这最终只是数据文档的问题。

【讨论】:

以上是关于切片时返回错误索引值的数据类型的主要内容,如果未能解决你的问题,请参考以下文章

python序列

为啥python的列表切片不会产生索引越界错误? [复制]

当尝试对 pandas 数据帧进行切片时,它会引发“ValueError('Lengths must match to compare')”

切片时的 if 语句

索引 切片 字符串数据类型

如何编写返回多种数据类型值的Java函数?