欢迎使用 Pack,这是一个 Swift 包,用于将各种数据类型序列化和反序列化为外部表示形式。
Pack 在功能上类似于内置的 Codable
协议,但是,与 Codable 不同,Pack 不是基于键/值对的,因此旨在打包和解包二进制数据以实现高效存储。
要序列化一些数据,可以使用 Packer
将数据打包到 Swift Data
对象中。 BinaryPack
对象符合 Packer
和 Unpacker
协议,并对 Swift 原始类型进行编码。
// Initialize a new Packer
let packer = BinaryPack()
// Pack an Integer
try packer.pack(12345)
// Pack a Double
try packer.pack(6789.0)
// Pack a String with utf8 encoding
try packer.pack("Hello, world!", using: .utf8)
由 Packer 序列化的数据可以作为 Swift Data
对象读取。
let packedData = packer.data
也可以使用 Unpacker
解码数据。
// Initialize a new Unpacker, and specify the data that should be unpacked
let unpacker = BinaryPack(from: data)
// Unpack an Integer
let int = try unpacker.unpack(Int.self)
// Unpack an Double
let double = try unpacker.unpack(Double.self)
// Unpack an String that was packed with utf8 encoding
let string = try unpacker.unpack(String.self, using: .utf8)
任何类型都可以符合 Packable
协议,从而允许对其进行序列化。 该类型也可以符合 Unpackable
协议,从而允许对其进行反序列化。 符合 Packed
协议的类型是 Packable
和 Unpackable
的简写,并且必须同时符合这两个协议。
例如,考虑以下表示命名颜色的结构。
struct Color {
let name: String
var red: Double
var green: Double
var blue: Double
var alpha: Double = 1.0
}
为了允许使用 Packer
序列化此结构,必须添加对 Packable
协议的符合性。
extension Color: Packable {
func pack(to packer: inout Packer) throws {
try packer.pack(name, using: .utf16)
try packer.pack(red)
try packer.pack(green)
try packer.pack(blue)
try packer.pack(alpha)
}
}
pack(to:)
函数提供了一个 Packer 作为inout变量,并且该函数应调用 Packer 上的函数来序列化其成员变量。
为了允许使用 Unpacker
反序列化此结构,必须添加对 Unpackable
协议的符合性。
extension Color: Unpackable {
init(from unpacker: inout Unpacker) throws {
self.name = try unpacker.unpack(String.self, using: .utf16)
self.red = try unpacker.unpack(Double.self)
self.green = try unpacker.unpack(Double.self)
self.blue = try unpacker.unpack(Double.self)
self.alpha = try unpacker.unpack(Double.self)
}
}
init(from:)
初始化器提供了一个 Unpacker 作为 inout 变量,并且该函数应调用 Packer 上的函数来反序列化其成员变量。
Pack 提供对流的序列化和反序列化的支持,例如写入内存或直接写入文件。
if let outputSteam = OutputStream(toFileAtPath: myFilePath, append: false) {
let packer = BinaryPack(writingTo: outputStream)
try packer.pack("Hello, World!", using: .ascii)
}
也可以从 InputStream
反序列化数据。
if let inputStream = InputStream(fileAtPath: myFilePath) {
let unpacker = BinaryPack(readingFrom: inputStream)
try unpacker.unpack(String.self, using: .ascii)
}
BinaryPack 是序列化和反序列化 Swift 内置类型作为二进制数据的标准打包器。 默认情况下,它在字符串数据之前写入字符串字节大小,确保可以轻松地读回。
初始化 BinaryPack 对象时,可以使用选项修改此行为。
例如,要在字符串后读取或写入空终止符,可以设置以下选项。
let binaryPack = BinaryPack(options: [.stringsNullTerminated])
由于 Pack 旨在序列化和反序列化原始二进制数据,因此打包数据的布局非常重要。 因此,除了原始内置值类型(例如 Int
、Double
、String
...等等)之外,Pack 不提供对打包或解包复杂 Swift 内置类型的支持。 因此,将 Pack 协议符合性添加到更复杂的内置类型留给最终用户,从而使他们可以确保以稳定的格式写出数据,以匹配用例。
Pack 使用 Swift Package Manager 分发。 要在另一个 Swift 包中安装它,请将其作为依赖项添加到您的 Package.swift
清单中。
let package = Package(
// . . .
dependencies: [
.package(url: "https://github.com/mattcox/Pack.git", branch: "main")
],
// . . .
)
如果您想在 Apple 平台上的应用程序中使用 Pack,请使用 Xcode 的 File > Add Packages...
菜单命令将其添加到您的项目中。
在您想要使用 Pack 的任何地方导入 Pack
import Pack