我有一个int32,浮点数和数据的Swift结构,我想将此结构实例保存为二进制格式-有人可以帮我如何以二进制格式编写或保存文件吗?
struct Another
{
let imgCount : __uint32_t
let resetFlag : __uint32_t
let focalX : float_t
let focalY : float_t
let somedata : Data
}
MemoryLayout<Another>.size
和MemoryLayout<Another>.stripe
也令人困惑。
答案 0 :(得分:2)
您将需要保留前16个字节(每个数字属性都保留4个字节,因为它们都是32位)。数据的尾部将用于数据属性someData
,该属性可以是任意大小:
struct Another {
// UInt32 - A 32-bit unsigned integer value type. You will need 4 bytes for each property
// 4 + 4 = 8 Bytes
let imgCount, resetFlag: UInt32
// Float - A single-precision, floating-point value type. Again 4 bytes for each property
// 4 + 4 = 8 Bytes
let focalX, focalY: Float
// the data can have any size this will be all bytes from index 16 until the end of the file
let someData: Data
}
要将数字类型转换为Data并返回,可以使用以下助手:
extension Numeric {
var data: Data {
var source = self
return Data(bytes: &source, count: MemoryLayout<Self>.size)
}
}
extension Data {
func object<T>() -> T {
return withUnsafeBytes { $0.pointee }
}
}
现在,您只需要创建一个自定义初始化程序即可对遍历数据的数据进行解码并设置相应的属性值。
extension Another {
init(_ data: Data) {
var startIndex = data.startIndex
var endIndex = startIndex.advanced(by: MemoryLayout<UInt32>.size)
let imgCountRange = startIndex..<endIndex
self.imgCount = data[imgCountRange].object()
startIndex = endIndex
endIndex = startIndex.advanced(by: MemoryLayout<UInt32>.size)
let resetFlagRange = startIndex..<endIndex
self.resetFlag = data[resetFlagRange].object()
startIndex = endIndex
endIndex = startIndex.advanced(by: MemoryLayout<Float>.size)
let focalXRange = startIndex..<endIndex
self.focalX = data[focalXRange].object()
startIndex = endIndex
endIndex = startIndex.advanced(by: MemoryLayout<Float>.size)
let focalYRange = startIndex..<endIndex
self.focalY = data[focalYRange].object()
self.someData = data[endIndex...]
}
}
对结构进行编码将容易得多:
extension Another {
var data: Data {
return imgCount.data + resetFlag.data + focalX.data + focalY.data + someData
}
}
测试:
let obj1 = Another(imgCount: 1, resetFlag: 2, focalX: 3.4, focalY: 5.6, someData: Data([0,1,2,3,4,5,6,7,8,9,10]))
let obj2 = Another(imgCount: 3, resetFlag: 4, focalX: 5.6, focalY: 7.8, someData: Data([10,11,12,13,14,15,16,17,18,19,20,21,22]))
let obj1Data = obj1.data
print(obj1Data) // 27 bytes
let obj1FromData = Another(obj1Data)
print(obj1FromData)
let obj2Data = obj2.data
print(obj2Data) // 29 bytes
let obj2FromData = Another(obj2Data)
print(obj2FromData)
这将打印
27个字节
另一个(imgCount:1,resetFlag:2,focusX:3.4,focusY:5.6, someData:11个字节)
29个字节
另一个(imgCount:3,resetFlag:4, focusX:5.6,focusY:7.8,someData:13个字节)
答案 1 :(得分:0)
尝试这种方式
struct Another : Codable {
let x: Int
let data: Data
}
let obj = Another(x: 10, data: Data("Hello world".utf8))
if let objData = try? JSONEncoder().encode(obj) {
print("encoded \(objData)")
// write this objData into file, or whatever u want
// now time to decoding this data into struct
if let secondObj = try? JSONDecoder().decode(Another.self, from: objData) {
print("decoded \(secondObj)")
}
} else {
print("encoding problem")
}
在这里,我仅放置结构的一部分,并为此准备Data
。您可以写入文件。再次从文件读取,您可以将Data
解码为对象。
要将Data
写入文件,请选中appledoc
func write(to url: URL, options: Data.WritingOptions = []) throws