Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert bytes/UInt8 array to Int in Swift

How to convert a 4-bytes array into the corresponding Int?

let array: [UInt8] ==> let value : Int 

Example:

Input:

\0\0\0\x0e 

Output:

14 

Some code I found on the internet that doesn't work:

let data = NSData(bytes: array, length: 4) data.getBytes(&size, length: 4) // the output to size is 184549376 
like image 273
Jerry Avatar asked Sep 24 '15 20:09

Jerry


People also ask

Is UInt8 a byte?

A uint8_t data type is basically the same as byte in Arduino. Writers of embedded software often define these types, because systems can sometimes define int to be 8 bits, 16 bits or 32 bits long. The issue doesn't arise in C# or Java, because the size of all the basic types is defined by the language.

What is UInt8 Swift?

An 8-bit unsigned integer value type.

What is byte array in Swift?

In Swift a byte is called a UInt8—an unsigned 8 bit integer. A byte array is a UInt8 array. In ASCII we can treat chars as UInt8 values. With the utf8 String property, we get a UTF8View collection. We can convert this to a byte array.


2 Answers

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.

like image 97
Martin R Avatar answered Sep 21 '22 11:09

Martin R


In Swift 3 it is now a bit more wordy:

let array : [UInt8] = [0, 0, 0, 0x0E] let bigEndianValue = array.withUnsafeBufferPointer {          ($0.baseAddress!.withMemoryRebound(to: UInt32.self, capacity: 1) { $0 }) }.pointee let value = UInt32(bigEndian: bigEndianValue) 
like image 20
ambientlight Avatar answered Sep 18 '22 11:09

ambientlight