¿Cómo convertir un doble en una matriz de bytes en swift?

Sé cómo hacerlo en Java (ver aquí ), pero no pude encontrar un equivalente rápido para ByteBuffer de Java, y en consecuencia su método .putDouble (valor doble).

Básicamente, estoy buscando una función como esta:

func doubleToByteArray(value: Double) -> [UInt8]? { . . . } doubleToByteArray(1729.1729) // should return [64, 155, 4, 177, 12, 178, 149, 234] 

 typealias Byte = UInt8 func toByteArray(var value: T) -> [Byte] { return withUnsafePointer(&value) { Array(UnsafeBufferPointer(start: UnsafePointer($0), count: sizeof(T))) } } toByteArray(1729.1729) toByteArray(1729.1729 as Float) toByteArray(1729) toByteArray(-1729) 

Pero los resultados se han revertido de sus expectativas (debido a endianness):

 [234, 149, 178, 12, 177, 4, 155, 64] [136, 37, 216, 68] [193, 6, 0, 0, 0, 0, 0, 0] [63, 249, 255, 255, 255, 255, 255, 255] 

Adicional:

 func fromByteArray(value: [Byte], _: T.Type) -> T { return value.withUnsafeBufferPointer { return UnsafePointer($0.baseAddress).memory } } let a: Double = 1729.1729 let b = toByteArray(a) // -> [234, 149, 178, 12, 177, 4, 155, 64] let c = fromByteArray(b, Double.self) // -> 1729.1729 

Para Xcode8 / Swift3.0:

 func toByteArray(_ value: T) -> [UInt8] { var value = value return withUnsafePointer(to: &value) { $0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size) { Array(UnsafeBufferPointer(start: $0, count: MemoryLayout.size)) } } } func fromByteArray(_ value: [UInt8], _: T.Type) -> T { return value.withUnsafeBufferPointer { $0.baseAddress!.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } } } 

Para Xcode8.1 / Swift3.0.1

 func toByteArray(_ value: T) -> [UInt8] { var value = value return withUnsafeBytes(of: &value) { Array($0) } } func fromByteArray(_ value: [UInt8], _: T.Type) -> T { return value.withUnsafeBytes { $0.baseAddress!.load(as: T.self) } } 

Bueno, no fue fácil, pero aquí está:

 func doubleToByteArray(value: Double) -> [UInt8] { let count = sizeof(Double) var doubles: [Double] = [value] let data = NSData(bytes: doubles, length: count) var result = [UInt8](count: count, repeatedValue: 0) data.getBytes(&result, length: count) return result } 

Usar con precaución.

Aquí está mi versión actualizada de la solución original.

 /// input: array of bytes /// -> get pointer to byte array (UnsafeBufferPointer< [Byte]>) /// -> access its base address /// -> rebind memory to target type T (UnsafeMutablePointer) /// -> extract and return the value of target type func binarytotype  (_ value: [Byte], _: T.Type) -> T { return value.withUnsafeBufferPointer { $0.baseAddress! .withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } } } /// input type: value of type T /// -> get pointer to value of T /// -> rebind memory to the target type, which is a byte array /// -> create array with a buffer pointer initialized with the source pointer /// -> return the resulted array func typetobinary  (_ value: T) -> [Byte] { var mv : T = value let s : Int = MemoryLayout.size return withUnsafePointer(to: &mv) { $0.withMemoryRebound(to: Byte.self, capacity: s) { Array(UnsafeBufferPointer(start: $0, count: s)) } } } 

PD: No te olvides de reemplazar Byte con UInt8.

Solución en Swift 3:

 public func toByteArray(_ value: T) -> [Byte] { let totalBytes = MemoryLayout.size var value = value return withUnsafePointer(to: &value) { valuePtr in return valuePtr.withMemoryRebound(to: Byte.self, capacity: totalBytes) { reboundPtr in return Array(UnsafeBufferPointer(start: reboundPtr, count: totalBytes)) } } } 

Las respuestas aceptadas son peligrosas por el hecho de que MemoryLayout proporciona el tamaño del tipo estático T !

Para solucionar el problema, debe crear un protocolo personalizado y solicitar Self en él:

 protocol ByteConvertible {} extension ByteConvertible { func toBytes() -> [UInt8] { let capacity = MemoryLayout.size var mutableValue = self return withUnsafePointer(to: &mutableValue) { return $0.withMemoryRebound(to: UInt8.self, capacity: capacity) { return Array(UnsafeBufferPointer(start: $0, count: capacity)) } } } } 

Mencioné antes que las respuestas aceptadas son peligrosas y aquí hay un ejemplo de por qué:

 let num = UInt8(42) MemoryLayout.size(ofValue: num) //=> 1 byte as expected let any: Any = num MemoryLayout.size(ofValue: any) //=> 32 bytes which is what will happen in the generic functions from the all the answers 

Swift 3.0

El método anterior funciona, usando Swift 2 pero, descubrí un método mucho más simple y rápido para hacer esta conversión y viceversa:

 func binarytotype  (value: [UInt8], _: T.Type) -> T { return value.withUnsafeBufferPointer { return UnsafePointer($0.baseAddress).memory } } func typetobinary  (var value: T) -> [UInt8] { return withUnsafePointer(&value) { Array(UnsafeBufferPointer(start: UnsafePointer($0), count: sizeof(T))) } } let a: Double = 0.25 let b: [UInt8] = typetobinary(a) // -> [0, 0, 0, 0, 0, 0, 208, 63] let c = binarytotype(b, Double.self) // -> 0.25 

Lo he probado con Xcode 7.2 en el patio de recreo.