Convert a two byte UInt8 array to a UInt16 in Swift
If you want to go via NSData
then it would work like this:
let bytes:[UInt8] = [0x01, 0x02]
println("bytes: \(bytes)") // bytes: [1, 2]
let data = NSData(bytes: bytes, length: 2)
print("data: \(data)") // data: <0102>
var u16 : UInt16 = 0 ; data.getBytes(&u16)
// Or:
let u16 = UnsafePointer<UInt16>(data.bytes).memory
println("u16: \(u16)") // u16: 513
Alternatively:
let bytes:[UInt8] = [0x01, 0x02]
let u16 = UnsafePointer<UInt16>(bytes).memory
print("u16: \(u16)") // u16: 513
Both variants assume that the bytes are in the host byte order.
Update for Swift 3 (Xcode 8):
let bytes: [UInt8] = [0x01, 0x02]
let u16 = UnsafePointer(bytes).withMemoryRebound(to: UInt16.self, capacity: 1) {
$0.pointee
}
print("u16: \(u16)") // u16: 513
How would I convert a [UInt8] to [UInt16] in Swift?
try something like:
var byteArr:[UInt8] = [126, 34, 119, 55, 1, 159, 144, 24, 108, 226, 49, 178, 60, 119, 133, 97, 189, 49, 111, 208]
var newArray:[UInt16] = byteArr.map { UInt16($0) }
map performs a function on each element of an array and returns a new array
Convert bytes/UInt8 array to Int in Swift
There are two problems:
Int
is a 64-bit integer on 64-bit platforms, your input data
has only 32-bit.Int
uses a little-endian representation on all current Swift platforms,
your input is big-endian.
That being said the following would work:
let array : [UInt8] = [0, 0, 0, 0x0E]
var value : UInt32 = 0
let data = NSData(bytes: array, length: 4)
data.getBytes(&value, length: 4)
value = UInt32(bigEndian: value)
print(value) // 14
Or using Data
in Swift 3:
let array : [UInt8] = [0, 0, 0, 0x0E]
let data = Data(bytes: array)
let value = UInt32(bigEndian: data.withUnsafeBytes { $0.pointee })
With some buffer pointer magic you can avoid the intermediate
copy to an NSData
object (Swift 2):
let array : [UInt8] = [0, 0, 0, 0x0E]
var value = array.withUnsafeBufferPointer({
UnsafePointer<UInt32>($0.baseAddress).memory
})
value = UInt32(bigEndian: value)
print(value) // 14
For a Swift 3 version of this approach, see ambientlight's answer.
Splitting a UInt16 to 2 UInt8 bytes and getting the hexa string of both. Swift
From your test cases, it seems like your values are 7 bits per byte.
You want 8192
to convert to 4000
.
You want 16383
to convert to 7F7F
.
Note that:
(0x7f << 7) + 0x7f == 16383
Given that:
let a = UInt8((int16 >> 7) & 0x7f)
let b = UInt8(int16 & 0x7f)
let result = String(format: "%02X%02X", a , b)
This gives:
"4000"
for 8128
"7F7F"
for 16383
To reverse the process:
let str = "7F7F"
let value = Int(str, radix: 16)!
let result = ((value >> 8) & 0x7f) << 7 + (value & 0x7f)
print(result) // 16383
How to convert UInt16 to UInt8 in Swift 3?
As the error message indicates, you have to use withMemoryRebound()
to reinterpret the pointer to UInt16
as a pointer to UInt8
:
let bytes = withUnsafePointer(to: &bigEndian) {
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: bigEndian)) {
Array(UnsafeBufferPointer(start: $0, count: MemoryLayout.size(ofValue: bigEndian)))
}
}
The closures are invoked with pointers ($0
) which are only valid
for the lifetime of the closure and must not be passed to the outside
for later use. That's why an Array
is created and used as return value.
There is a simpler solution however:
let bytes = withUnsafeBytes(of: &bigEndian) { Array($0) }
Explanation: withUnsafeBytes
invokes the closure with a UnsafeRawBufferPointer
to the storage of the bigEndian
variable.
Since UnsafeRawBufferPointer
is a Sequence
of UInt8
, an array
can be created from that with Array($0)
.
Swift convert [UIn16] to UnsafeMutablePointerUInt16
The withXXXBytes
methods get you raw pointers, but here you want a typed pointer. Use withUnsafeMutableBufferPointer
instead and get the base address:
arrayOfUInt16.withUnsafeMutableBufferPointer { (bufferPointer) in
let mutablePointerOfUInt16 = bufferPointer.baseAddress
// do whatever you want with mutablePointerOfUInt16
// just don't "store or return the pointer for later use." as the documentation says
// because the pointer is only valid within this block
}
How in swift to convert Int16 to two UInt8 Bytes
You should work with unsigned integers:
let bytes: [UInt8] = [255, 251]
let uInt16Value = UInt16(bytes[0]) << 8 | UInt16(bytes[1])
let uInt8Value0 = uInt16Value >> 8
let uInt8Value1 = UInt8(uInt16Value & 0x00ff)
If you want to convert UInt16 to bit equivalent Int16 then you can do it with specific initializer:
let int16Value: Int16 = -15
let uInt16Value = UInt16(bitPattern: int16Value)
And vice versa:
let uInt16Value: UInt16 = 65000
let int16Value = Int16(bitPattern: uInt16Value)
In your case:
let nv: Int16 = -15
let uNv = UInt16(bitPattern: nv)
UInt8(uNv >> 8)
UInt8(uNv & 0x00ff)
Related Topics
Removeobjectsatindexes For Swift Arrays
Express For Loops in Swift With Dynamic Range
Value of Type 'Storagemetadata' Has No Member 'Downloadurl'
Swift - Spritekit Cgpoint Alignment
What Is Geometry Reader in Swiftui
Getting "File Not Found" in Bridging Header When Importing Objective-C Frameworks into Swift Project
Swift Random Float Between 0 and 1
How to Unwrap Double Optionals
Instance Member Cannot Be Used on Type
How to Convert a View (Not Uiview) to an Image
Swift 2 - Pattern Matching in "If"
Closure With Generic Parameters
Arkit - What Do the Different Columns in Transform Matrix Represent