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