【问题标题】:How to convert different type values to data byte如何将不同类型的值转换为数据字节
【发布时间】:2019-02-01 07:10:51
【问题描述】:

我正在编写一个应用程序,我需要将一个不同数据类型的数组转换为一个数据数组,我将通过 UDP 端口发送到另一个设备。

到目前为止,我有以下代码:

class ViewController: NSViewController {
  override func viewDidLoad() {
    super.viewDidLoad()

    let a: UInt8 = 42

    var da:[UInt8] = [a]
    let data = Data(buffer: UnsafeBufferPointer(start: &da, count: da.count))
    let x = data.toArray(type: UInt8.self)
    print(x)
  }
}

到目前为止,这是可行的。我得到以下输出:[42]
如果我将let a: UInt8 = 42 更改为let a: Float = 3.14var da:[Float] = [a],我会得到[195, 245, 72, 64] 的结果。

以上都是我所期望的。问题出在以下代码中:

class ViewController: NSViewController {
  override func viewDidLoad() {
    super.viewDidLoad()

    let b: UInt8 = 42
    let a: Float = 3.14

    var da:[Any] = [a, b]
    let data = Data(buffer: UnsafeBufferPointer(start: &da, count: da.count))
    let x = data.toArray(type: UInt8.self)
    print(x)
  }
}

在这里,我希望得到[42, 195, 245, 72, 64],除非我得到以下结果:[42, 0, 0, 0, 0, 0, 0, 0, 176, 10, 10, 0, 0, 96, 0, 0, 104, 41, 172, 143, 255, 127, 0, 0, 32, 161, 114, 0, 1, 0, 0, 0, 195, 245, 72, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 228, 32, 1, 1, 0, 0, 0, 168, 153, 114, 0, 1, 0, 0, 0]

有人可以向我解释为什么会发生这种情况以及我应该改变什么以获得预期的结果吗?

编辑:虽然我可以跳过填充,但我在开发应用程序时试图伪造来自以下规范的服务器。
https://forums.codemasters.com/discussion/136948/f1-2018-udp-specification#latest

【问题讨论】:

  • @LeoDabus 查看我的编辑。
  • 忘记任何方法的数组。您需要手动编写数据
  • @LeoDabus 所以你的意思是我必须将每个值转换为数据,然后将其转换为数组并将该数组合并为一个大数组?

标签: arrays swift macos types nsdata


【解决方案1】:

您看到的是Any 的内部存储器表示。

print(MemoryLayout<Any>.size) //-> 32

Any 类型的值表示在一个大小为 32 的隐藏结构中,其中可能包含一些原始数据的原始值或引用类型实例或巨大结构的地址,以及有关该类型的一些元数据包含的值。

这不是一个简单的填充。


你可以这样写:

(如果需要,您可能需要自己控制 填充。)

protocol ByteRepresentable {
    var bytes: Data {get}
}
extension ByteRepresentable {
    var bytes: Data {
        var copiedSelf = self
        return Data(bytes: &copiedSelf, count: MemoryLayout.size(ofValue: self))
    }
}
extension UInt8: ByteRepresentable {}
extension Float: ByteRepresentable {}
//...

let a: UInt8 = 42
let b: Float = 3.14

let da: [ByteRepresentable] = [a, b]
var data = da.reduce(into: Data(), {$0.append($1.bytes)})
print(Array(data)) //->[42, 195, 245, 72, 64]

如果你想写一个扩展:

extension Array where Element == ByteRepresentable {
    func toData() -> Data {
        return self.reduce(into: Data(), {$0.append($1.bytes)})
    }
}

print(Array(da.toData())) //->[42, 195, 245, 72, 64]

【讨论】:

  • MemoryLayout&lt;Self&gt;.size
  • @LeoDabus,谢谢,这可能是一个可能的选择。
  • 行得通!谢谢你。有没有办法做一个Array&lt;ByteRepresentable&gt;.toData() -&gt; Data 函数而不是一直做var data = da.reduce(into: Data(), {$0.append($1.bytes)})
  • @iProgram,是的,您可以为 Array 编写类型约束扩展。
猜你喜欢
  • 2010-11-26
  • 2020-12-13
  • 1970-01-01
  • 2010-10-18
  • 2018-08-17
  • 2022-10-07
  • 1970-01-01
  • 2015-07-23
相关资源
最近更新 更多