2015-04-30 155 views
2

我想將UInt32添加到我使用的字節緩衝區[UInt8]。在java中,有一個方便的ByteBuffer類,它有像putInt()這樣的方法。這怎麼能迅速完成呢?swift將UInt32拆分爲[UInt8]

我想我可以解決這個問題如下:

let example: UInt32 = 72 << 24 | 66 << 16 | 1 << 8 | 15 
var byteArray = [UInt8](count: 4, repeatedValue: 0) 

for i in 0...3 { 
    byteArray[i] = UInt8(0x0000FF & example >> UInt32((3 - i) * 8)) 
} 

這是相當冗長不過,任何簡單的方法?

回答

8

你的循環可以更緊湊地寫爲

let byteArray = 24.stride(through: 0, by: -8).map { 
    UInt8(truncatingBitPattern: example >> UInt32($0)) 
} 

可選擇地,創建一個UnsafeBufferPointer並轉換該 到數組:

let example: UInt32 = 72 << 24 | 66 << 16 | 1 << 8 | 15 

var bigEndian = example.bigEndian 
let bytePtr = withUnsafePointer(&bigEndian) { 
    UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: sizeofValue(bigEndian)) 
} 
let byteArray = Array(bytePtr) 

print(byteArray) // [72, 66, 1, 15] 

更新夫特3(Xcode的8個β6) :

var bigEndian = example.bigEndian 
let count = MemoryLayout<UInt32>.size 
let bytePtr = withUnsafePointer(to: &bigEndian) { 
    $0.withMemoryRebound(to: UInt8.self, capacity: count) { 
     UnsafeBufferPointer(start: $0, count: count) 
    } 
} 
let byteArray = Array(bytePtr) 
+0

謝謝!乍看之下,這個循環似乎很難閱讀,但它確實更加緊湊。 – Kelo

3

您可以投從一個UnsafeMutablePointer類型到另:

var arr = UnsafeMutablePointer<UInt32>.alloc(1) 
arr.memory = example 
var arr2 = UnsafeMutablePointer<UInt8>(arr) 
0

我有一個類似的問題在Xcode 8 Beta中6: 寫此行

var value = String(cString: sqlite3_column_text(stmt, index)) 

    to 


let txt = UnsafePointer<Int8>(sqlite3_column_text(stmt, index)) 

和解決問題

1

改進@馬丁R的回答。在UInt16,UInt32和UInt64上工作:

protocol UIntToBytesConvertable { 
    var toBytes: [Byte] { get } 
} 

extension UIntToBytesConvertable { 
    func toByteArr<T: Integer>(endian: T, count: Int) -> [Byte] { 
     var _endian = endian 
     let bytePtr = withUnsafePointer(to: &_endian) { 
      $0.withMemoryRebound(to: Byte.self, capacity: count) { 
       UnsafeBufferPointer(start: $0, count: count) 
      } 
     } 
     return [Byte](bytePtr) 
    } 
} 

extension UInt16: UIntToBytesConvertable { 
    var toBytes: [Byte] { 
     return toByteArr(endian: self.littleEndian, 
         count: MemoryLayout<UInt16>.size) 
    } 
} 

extension UInt32: UIntToBytesConvertable { 
    var toBytes: [Byte] { 
     return toByteArr(endian: self.littleEndian, 
         count: MemoryLayout<UInt32>.size) 
    } 
} 

extension UInt64: UIntToBytesConvertable { 
    var toBytes: [Byte] { 
     return toByteArr(endian: self.littleEndian, 
         count: MemoryLayout<UInt64>.size) 
    } 
} 
0

改進@Martin R的回答。

func toByteArrary<T>(value: T) -> [UInt8] where T: UnsignedInteger, T: FixedWidthInteger{ 
    var bigEndian = value.bigEndian 
    let count = MemoryLayout<T>.size 
    let bytePtr = withUnsafePointer(to: &bigEndian) { 
    $0.withMemoryRebound(to: UInt8.self, capacity: count) { 
     UnsafeBufferPointer(start: $0, count: count) 
    } 
    } 

    return Array(bytePtr) 
}