Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在swift中将double转换为字节数组?_Ios_Swift_Byte_Bytearray_Bytebuffer - Fatal编程技术网

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

Ios 如何在swift中将double转换为字节数组?,ios,swift,byte,bytearray,bytebuffer,Ios,Swift,Byte,Bytearray,Bytebuffer,我知道如何在java中实现它(请参阅),但我找不到java的ByteBuffer的swift等价物,因此也找不到它的.putDouble(double value)方法。 基本上,我在寻找这样的函数: func doubleToByteArray(value: Double) -> [UInt8]? { . . . } doubleToByteArray(1729.1729) // should return [64, 155, 4, 177, 12, 178, 149, 234]

我知道如何在java中实现它(请参阅),但我找不到java的ByteBuffer的swift等价物,因此也找不到它的.putDouble(double value)方法。

基本上,我在寻找这样的函数:

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

增加:

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
func fromByteArray(值:[字节],\uU:T.Type)->T{
返回值.withUnsafeBufferPointer{
返回未安全指针($0.baseAddress)。内存
}
}
设a:Double=1729.1729
设b=toByteArray(a)/->[23414917812177,415564]
设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
        }
    }
}
func-toByteArray(u值:T)->[UInt8]{
var值=价值
返回withUnsafePointer(指向:&值){
$0.带MemoryRebound(收件人:UInt8.self,容量:MemoryLayout.size){
数组(UnsafeBufferPointer(开始:$0,计数:MemoryLayout.size))
}
}
}
func fromByteArray(0值:[UInt8],0:T.Type)->T{
返回值.withUnsafeBufferPointer{
$0.baseAddress!.withMemoryRebound(收件人:T.self,容量:1){
0.1元
}
}
}

对于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-toByteArray(u值:T)->[UInt8]{
var值=价值
返回withUnsafeBytes(of:&值){Array($0)}
}
func fromByteArray(0值:[UInt8],0:T.Type)->T{
返回值.withUnsafeBytes{
$0.baseAddress!.load(作为: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
}

小心使用。

上述方法在使用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
func二进制类型(值:[UInt8],\uu:T.Type)->T
{
返回值.withUnsafeBufferPointer
{
返回未安全指针($0.baseAddress)。内存
}
}
函数类型二进制(变量值:T)->[UInt8]
{
返回带unsafepointer(&value)
{
数组(UnsafeBufferPointer(开始:UnsafePointer($0),计数:sizeof(T)))
}
}
设a:Double=0.25
设b:[UInt8]=typetobinary(a)/->[0,0,0,0,0,208,63]
设c=binarytotype(b,Double.self)/->0.25

我已经在操场上用Xcode 7.2对它进行了测试。

这是我对原始解决方案的更新版本

/// 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))
        }
    }
}
///输入:字节数组
///->获取指向字节数组的指针(UnsafeBufferPointer)
///->访问其基址
///->将内存重新绑定到目标类型T(不可配置指针)
///->提取并返回目标类型的值
func二进制类型(u值:[字节],u:T.Type)->T
{
返回值.withUnsafeBufferPointer{
$0.5基本地址!
.带记忆封套(收件人:T.self,容量:1){
0.1元
}
}
}
///输入类型:类型T的值
///->获取指向T值的指针
///->将内存重新绑定到目标类型,即字节数组
///->使用源指针初始化的缓冲区指针创建数组
///->返回结果数组
函数类型二进制(u值:T)->[字节]
{
var mv:T=值
设s:Int=MemoryLayout.size
返回未安全指针(指向:&mv){
$0.withMemoryRebound(至:Byte.self,容量:s){
数组(UnsafeBufferPointer(开始:$0,计数:s))
}
}
}
PS:别忘了用UInt8替换字节。

swift 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))
    }
  }
}
public func toByteArray(u值:T)->[Byte]{
让totalBytes=MemoryLayout.size
var值=价值
返回withUnsafePointer(to:&value){valuePtr in
返回值ptr.withMemoryRebound(to:Byte.self,capacity:totalBytes){n中的ptr
返回数组(UnsafeBufferPointer(开始:REBOCKPTR,计数:totalBytes))
}
}
}

接受的答案是危险的,因为
MemoryLayout
提供了静态类型
T
的大小

要解决此问题,您应该创建一个自定义协议,并在其中请求
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))
            }
        }
    }
}
Swift 3.0

func byteArray(u值:T)->[UInt8]{
var值=价值
var initialArray=withUnsafeBytes(of:&value){Array($0)}
initialArray.reverse()
var count=initialArray.count
而initialArray.first==0&&count>1{
initialArray[0…计数-2]=initialArray[1…计数-1]
计数-=1
}
如果initialArray[0]>=128{
var newArray=[UInt8](重复:0,计数:计数+1)
newArray[0]=UInt8(0)
newArray[1…计数]=initialArray[0…计数-1]
返回新数组
}否则{
返回数组(初始数组[0…计数-1])
}
}

只需使用
toByteArray(1729.1729).reverse()
即可获得所需的顺序。我建议使用
CFByteOrder.h
中定义的函数,例如
toByteArray(CfConvertDoubleHostToSwap(1729.1729.v)
。我添加了
typealias Byte=UInt8
,因为
Byte
不是本机数据类型。:-)如果您使用第一个函数将数据序列化到某个非Swift平台,请注意。如果您向它传递一个“可选”Swift值类型,那么它会向输出中添加一个额外的字节,可能是为了指示该值是否为零。所以给它一个UInt64?值生成9个字节,而不是8个字节。避免这种情况的一种方法是将“value”的参数类型从T改为T?,然后将第一条语句替换为“var value=value!”。它崩溃了:我想在Swift 3 beta 6和新的withMemoryRebound命令中使用它。有人知道如何将其转换为swift 3 beta 6吗?
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))
    }
  }
}
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 
func byteArray<T>(_ value: T) -> [UInt8] {
    var value = value
    var initialArray = withUnsafeBytes(of: &value) { Array($0) }

    initialArray.reverse()
    var count = initialArray.count
    while initialArray.first == 0 && count > 1 {
        initialArray[0...count - 2] = initialArray[1...count - 1]
        count -= 1
    }
    if initialArray[0] >= 128 {
        var newArray = [UInt8](repeating: 0, count: count + 1)
        newArray[0] = UInt8(0)
        newArray[1...count] = initialArray[0...count - 1]
        return newArray
    } else {
        return Array(initialArray[0...count - 1])
    }
}