How in Swift to Convert Int16 to Two Uint8 Bytes

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)

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

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

Convert Int to Array of UInt8 in swift

You could do it this way:

let x: Int = 2019
let length: Int = 2 * MemoryLayout<UInt8>.size //You could specify the desired length

let a = withUnsafeBytes(of: x) { bytes in
Array(bytes.prefix(length))
}

let result = Array(a.reversed()) //[7, 227]

Or more generally, we could use a modified version of this snippet:

func bytes<U: FixedWidthInteger,V: FixedWidthInteger>(
of value : U,
to type : V.Type,
droppingZeros: Bool
) -> [V]{

let sizeInput = MemoryLayout<U>.size
let sizeOutput = MemoryLayout<V>.size

precondition(sizeInput >= sizeOutput, "The input memory size should be greater than the output memory size")

var value = value
let a = withUnsafePointer(to: &value, {
$0.withMemoryRebound(
to: V.self,
capacity: sizeInput,
{
Array(UnsafeBufferPointer(start: $0, count: sizeInput/sizeOutput))
})
})

let lastNonZeroIndex =
(droppingZeros ? a.lastIndex { $0 != 0 } : a.indices.last) ?? a.startIndex

return Array(a[...lastNonZeroIndex].reversed())
}

let x: Int = 2019
bytes(of: x, to: UInt8.self, droppingZeros: true) // [7, 227]
bytes(of: x, to: UInt8.self, droppingZeros: false) // [0, 0, 0, 0, 0, 0, 7, 227]

Convert parts of [UInt8] into UInt8

Given an array :

let bytes: [UInt8] = [204, 74, 3, 0, 97, 168, 209, 239]

let's get the length of the message:

let length = Int(bytes[2])

msg is the variable that will store the result:

var msg = 0

index will point to the indexes of the octets of the whole message, from the LSB (higher index in bytes), to the MSB (lower index in bytes)

var index = bytes.count - 3

power is the power with which we'll be shifting the octets

var power = 1

Then we calculate the message this way :

while index > 2 {
msg += Int(bytes[index]) * power
power = power << 8
index -= 1
}

The result is :

print(msg)  //25000

Or as @JoshCaswell suggests :

var msg: UInt64 = 0
var index = 3
while index < bytes.count - 2 {
msg <<= 8 //msg = msg << 8
msg += UInt64(bytes[index])
index += 1
}

In both solutions, we suppose that the message can fit into an Int or UInt64

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.

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



Related Topics



Leave a reply



Submit