Swift中的二进制文件IO

Tom*_*usX 6 ios swift

编辑:TLDR在C系列语言中,您可以通过转换将任意数据(整数,浮点数,双精度,结构)表示为字节流,并将它们打包到流或缓冲区中.你可以反过来取回数据.当然,你可以字节交换字节顺序正确性.

这在惯用语中是否可行?

现在原来的问题:

如果我用C/C++/ObjC编写,我可能会将一个结构转换为unsigned char*并将其字节写入FILE*,或将它们memcpy到缓冲区.对于整数,双打等也是如此.我知道有一些关于endianness的问题需要处理,但这适用于iOS应用程序,并且我不认为endianness会在不久的将来更改平台.Swift的类型系统似乎不允许这种行为(将任意数据转换为无符号8位整数并传递地址),但我不知道.

我正在学习Swift,并希望用一种惯用的方式来编写我的数据.请注意,我的数字很高,最终将通过网络发送,因此它需要紧凑,所以像JSON这样的文本格式已经出来了.

可以使用NSKeyedArchiver,但我想在这里学习.此外,我不想在未来的某个时刻注销一个Android客户端,所以一个简单的二进制编码似乎在它的位置.

有什么建议?

ric*_*ter 5

如所指出的使用夫特与可可和Objective-C ,可以传递/分配夫特型的阵列,以指针类型,反之亦然的参数/变量,来获得的二进制表示.如果您定义自己的struct类型,这甚至可以工作,就像在C.

这是一个例子 - 我使用这样的代码来封装GPU的3D顶点数据(使用SceneKit,OpenGL等):

struct Float3 {
    var x, y, z: GLfloat
}
struct Vertex {
    var position, normal: Float3
}

var vertices: [Vertex] // initialization omitted for brevity
let data = NSData(bytes: vertices, length: vertices.count * sizeof(Vertex))
Run Code Online (Sandbox Code Playgroud)

检查这些数据,您将看到32*3*2位IEEE 754浮点数的模式(就像您通过指针访问序列化C结构一样).

为了走向另一个方向,您有时可能需要unsafeBitCast.

如果您将其用于数据持久性,请务必检查或强制使用字节顺序.


Rob*_*ier 4

您正在讨论的格式类型已通过MessagePack得到了很好的探索。在 Swift 中,有一些早期的尝试:

我可能会从 yageek 版本开始。特别是,看看如何打包到[Byte]数据结构中。我想说这是非常惯用的 Swift,不会失去字节序管理(你不应该忽略它;芯片确实会改变,数字类型给你 via bigEndian):

extension Int32 : MsgPackMarshable{
  public func msgpack_marshal() -> Array<Byte>{

        let bigEndian: UInt32 = UInt32(self.bigEndian)
        return [0xce, Byte((bigEndian & 0xFF000000) >> 24), Byte((bigEndian & 0xFF0000) >> 16), Byte((bigEndian & 0xFF00) >> 8), Byte(bigEndian & 0x00FF)]
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您管理字节顺序,这也与您在 C 或 C++ 中编写它的方式非常相似(C 和 C++ 应该始终这样做,因此它们可以将字节放入内存的事实并不会让正确的实现变得微不足道) 。我可能会放弃Byte(来自 Foundation)并使用UInt8(在 Swift 核心中定义)。但两者都可以。当然,“说”[UInt8]比“说”更惯用Array<UInt8>

正如 Zaph 所说,这NSKeyedArchiver对于 Swift 来说是惯用的。但这并不意味着 MessagePack 不是解决此类问题的好格式,而且它非常便携。