ios - कैसे तेजी में एक बाइट सरणी में एक डबल परिवर्तित करने के लिए?




swift byte (5)

इस तथ्य के कारण स्वीकार किए गए उत्तर खतरनाक हैं कि 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))
            }
        }
    }
}

मैंने पहले उल्लेख किया है कि स्वीकृत उत्तर खतरनाक हैं और यहाँ एक उदाहरण है कि क्यों:

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 

स्विफ्ट 3.0

मुझे पता है कि इसे जावा में कैसे करना है ( here देखें), लेकिन मैं जावा के बाइटबफ़र के लिए एक तेज समकक्ष नहीं पा सका, और इसके परिणामस्वरूप .putDouble (डबल मूल्य) विधि।

असल में, मैं इस तरह एक समारोह के लिए देख रहा हूँ:

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

ऊपर की विधि काम करती है, स्विफ्ट 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 के साथ परीक्षण किया है।


यहाँ मूल समाधान के लिए मेरा अद्यतन संस्करण है।

/// 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))
        }
    }
}

पुनश्च: बाइट को UInt8 से बदलना न भूलें।


स्विफ्ट 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))
    }
  }
}

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)
    }
}




bytebuffer