将swift结构保存/写入为文件或二进制格式

时间:2019-02-18 14:04:14

标签: swift struct

我有一个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>.sizeMemoryLayout<Another>.stripe也令人困惑。

2 个答案:

答案 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