如何在Swift中将double转换为字节数组?

我知道如何在java(见这里 )中做到这一点,但我找不到一个快速的等效的Java的ByteBuffer,因此它的.putDouble(double值)方法。

基本上,我正在寻找这样的function:

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

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

但结果与您的期望相反(因为字节顺序):

 [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] 

添加:

 func fromByteArray<T>(value: [Byte], _: T.Type) -> T { return value.withUnsafeBufferPointer { return UnsafePointer<T>($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 

对于Xcode8 / Swift3.0:

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

对于Xcode8.1 / Swift3.0.1

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

那么,这并不容易,但这里是:

 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 } 

谨慎使用。

这是我的更新版本到原来的解决scheme。

 /// input: array of bytes /// -> get pointer to byte array (UnsafeBufferPointer<[Byte]>) /// -> access its base address /// -> rebind memory to target type T (UnsafeMutablePointer<T>) /// -> extract and return the value of target type func binarytotype <T> (_ 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 <T> (_ value: T) -> [Byte] { var mv : T = value let s : Int = MemoryLayout<T>.size return withUnsafePointer(to: &mv) { $0.withMemoryRebound(to: Byte.self, capacity: s) { Array(UnsafeBufferPointer(start: $0, count: s)) } } } 

PS:不要忘记用UInt8replace字节。

解决scheme在3:

 public func toByteArray<T>(_ value: T) -> [Byte] { let totalBytes = MemoryLayout<T>.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)) } } } 

上面的方法工作,使用Swift 2,但是,我发现了一个更简单快捷的方法来做这个转换,反之亦然:

 func binarytotype <T> (value: [UInt8], _: T.Type) -> T { return value.withUnsafeBufferPointer { return UnsafePointer<T>($0.baseAddress).memory } } func typetobinary <T> (var value: T) -> [UInt8] { return withUnsafePointer(&value) { Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>($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 

我已经在操场上用Xcode 7.2进行了testing。

被接受的答案是危险的,因为MemoryLayout为你提供了静态typesT的大小!

为了解决这个问题,你应该创build一个自定义协议,并要求Self

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

我之前提到,接受的答案是危险的,这就是为什么:

 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

Interesting Posts