NSData的轉換爲整數在Objective-C的代碼看起來很喜歡這個和完美地工作,在斯威夫特
NSInteger random = arc4random_uniform(99) + 1
NSData *data = [NSData dataWithBytes:& random length: sizeof(random)];
int value = *(int*)([data bytes]);
這怎麼能在斯威夫特做?
NSData的轉換爲整數在Objective-C的代碼看起來很喜歡這個和完美地工作,在斯威夫特
NSInteger random = arc4random_uniform(99) + 1
NSData *data = [NSData dataWithBytes:& random length: sizeof(random)];
int value = *(int*)([data bytes]);
這怎麼能在斯威夫特做?
像這樣:
var src: NSInteger = 2525
var out: NSInteger = 0
let data = NSData(bytes: &src, length: sizeof(NSInteger))
data.getBytes(&out, length: sizeof(NSInteger))
println(out) // ==> 2525
如果你是做了很多你可能會發現這個方法有用:
func readInteger<T : IntegerType>(data : NSData, start : Int) -> T {
var d : T = 0
data.getBytes(&d, range: NSRange(location: start, length: sizeof(T)))
return d
}
函數作爲參數數據的起始位置讀取數字類型,並返回從您分配的任何類型推斷出的某個類型的值。
例如:
let i : UInt32 = readInteger(data, 10);
讀取位置10在該數據中的4字節整數。
如果將UInt32
更改爲UInt16
,它將讀取兩個字節。
請詳細說明如何使用它以及通過哪些參數......謝謝。 – 2016-03-04 15:21:17
對於斯威夫特3,你可以這樣做(小端,但對於大的類似):
func getInt(fromData data: Data, start: Int) -> Int32 {
let intBits = data.withUnsafeBytes({(bytePointer: UnsafePointer<UInt8>) -> Int32 in
bytePointer.advanced(by: start).withMemoryRebound(to: Int32.self, capacity: 4) { pointer in
return pointer.pointee
}
})
return Int32(littleEndian: intBits)
}
您可以修改這一點,添加仿製藥等,以適應其他的基本類型(它取決於變化數據字節的字節序)。
這真的讓我對Swift感到厭煩。對於技術上非常簡單的東西,這是非常複雜的事情。我不知道編譯器是否優化了所有的bs – 2017-08-02 09:31:50
數據到整數感謝@rghome
// MARK: - Extensions Data
extension Data {
/// To interger Data by range
///
/// - Parameters:
/// - data: Data
/// - startRange: StartRange
/// - endRange: EndRange
/// - Returns: Integer Typed
func toInterger<T : Integer>(withData data: NSData, withStartRange startRange: Int, withSizeRange endRange: Int) -> T {
var d : T = 0
(self as NSData).getBytes(&d, range: NSRange(location: startRange, length: endRange))
return d
}
}
101010
let value:Int = Data().toInterger(withStartRange: 0, withEndRange: 2)
get 10
get 2 Int
謝謝@rghome :) – YannickSteph 2017-03-06 22:06:43
我與迅速延伸3.1的貢獻:
extension NSData{
var int : Int{
var out: Int = 0
self.getBytes(&out, length: MemoryLayout<Int>.size)
return out
}
}
只需撥打.INT讓你的價值,就像這樣:
let value = 50
let data = NSData(bytes: &value, length: 4)
print(data.int)
從Data
流中提取整數值時需要考慮幾件事情。 簽名和Endianess。所以我想出了一個擴展功能Data
,推斷簽名從你想要提取的整數類型,並通過Endianess和Index
作爲參數。可以提取的整數類型都符合FixedWidthInteger
協議。
提醒:本函數不能檢查Index
範圍是Data
緩衝器的邊界內,以便它可以根據在相對於被提取到緩衝區的端部的類型的大小崩潰。
extension Data {
enum Endianness {
case BigEndian
case LittleEndian
}
func scanValue<T: FixedWidthInteger>(at index: Data.Index, endianess: Endianness) -> T {
let number: T = self.subdata(in: index..<index + MemoryLayout<T>.size).withUnsafeBytes({ $0.pointee })
switch endianess {
case .BigEndian:
return number.bigEndian
case .LittleEndian:
return number.littleEndian
}
}
}
實施例:
let data = Data(bytes: [0xFF,0x1F,0x1F,0xFF])
let number1 = data.scanValue(at: 0, endianess: .LittleEndian) as UInt16
let number2 = data.scanValue(at: 0, endianess: .BigEndian) as UInt16
let number3: Int16 = data.scanValue(at: 2, endianess: .LittleEndian)
let number4: Int16 = data.scanValue(at: 2, endianess: .BigEndian)
結果:
number1 is 8191
number2 is 65311
number3 is -225
number4 is 8191
觀察函數調用以查看如何推斷出要提取的類型。當然Endianess對Int8
或UInt8
沒有意義,但該函數按預期工作。
如果需要,可以稍後將值轉換爲Int
。
嗨 - 有沒有更簡單的解決方案,只是將數據<02>轉換爲UInt8 2或Int 2? – richc 2017-10-05 13:34:54
@richc:獲得'UInt8'的最簡單方法是簡單地使用下標,如果你確切知道你想要的字節的索引:'data [index]' – 2017-10-08 03:12:41
絕對完美!謝謝! – dhint4 2014-10-07 03:23:19
或'sizeofValue(random)' – newacct 2014-10-07 19:24:11
在Swift3中:sizeof(NSInteger)變爲MemoryLayout .size並且println變爲打印。 –
parleer
2016-11-19 17:32:53