Сохранение / запись быстрых структур в виде файла или двоичного формата - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть Swift-структура int32, числа с плавающей запятой и данные, и я хочу сохранить этот экземпляр структуры в двоичном формате. Может ли кто-нибудь помочь мне с тем, как написать или сохранить файл в двоичном формате?

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 сбивают с толку.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Вам необходимо зарезервировать первые 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
}

Для преобразования числовых типов в данные и обратно вы можете использовать следующие помощники:

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, focalX: 3.4, focalY: 5.6, someData: 11 байтов)

29 байтов

Другой (imgCount: 3, resetFlag: 4, focalX: 5.6, focalY: 7.8, некоторые данные: 13 байтов)

0 голосов
/ 18 февраля 2019

Попробуйте вот так

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...