Binary to Hexadecimal in Swift

Binary to hexadecimal in Swift

A possible solution:

func binToHex(bin : String) -> String {
// binary to integer:
let num = bin.withCString { strtoul($0, nil, 2) }
// integer to hex:
let hex = String(num, radix: 16, uppercase: true) // (or false)
return hex
}

This works as long as the numbers fit into the range of UInt (32-bit or 64-bit,
depending on the platform). It uses the BSD library function strtoul() which converts a string to an integer according to a given base.

For larger numbers you have to process the input
in chunks. You might also add a validation of the input string.

Update for Swift 3/4: The strtoul function is no longer needed.
Return nil for invalid input:

func binToHex(_ bin : String) -> String? {
// binary to integer:
guard let num = UInt64(bin, radix: 2) else { return nil }
// integer to hex:
let hex = String(num, radix: 16, uppercase: true) // (or false)
return hex
}

Convert between Decimal, Binary and Hexadecimal in Swift

Both String and Int have initializers which take a radix (base). Combining those, you can achieve all of the conversions:

// Decimal to binary
let d1 = 21
let b1 = String(d1, radix: 2)
print(b1) // "10101"

// Binary to decimal
let b2 = "10110"
let d2 = Int(b2, radix: 2)!
print(d2) // 22

// Decimal to hexadecimal
let d3 = 61
let h1 = String(d3, radix: 16)
print(h1) // "3d"

// Hexadecimal to decimal
let h2 = "a3"
let d4 = Int(h2, radix: 16)!
print(d4) // 163

// Binary to hexadecimal
let b3 = "10101011"
let h3 = String(Int(b3, radix: 2)!, radix: 16)
print(h3) // "ab"

// Hexadecimal to binary
let h4 = "face"
let b4 = String(Int(h4, radix: 16)!, radix: 2)
print(b4) // "1111101011001110"

How to convert hex number to bin in Swift?

You can use NSScanner() from the Foundation framework:

let scanner = NSScanner(string: str)
var result : UInt32 = 0
if scanner.scanHexInt(&result) {
println(result) // 37331519
}

Or the BSD library function strtoul()

let num = strtoul(str, nil, 16)
println(num) // 37331519

As of Swift 2 (Xcode 7), all integer types have an

public init?(_ text: String, radix: Int = default)

initializer, so that a pure Swift solution is available:

let str = "239A23F"
let num = Int(str, radix: 16)

How to convert Data to hex string in swift

A simple implementation (taken from How to hash NSString with SHA1 in Swift?, with an additional option for uppercase output) would be

extension Data {
struct HexEncodingOptions: OptionSet {
let rawValue: Int
static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}

func hexEncodedString(options: HexEncodingOptions = []) -> String {
let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
return self.map { String(format: format, $0) }.joined()
}
}

I chose a hexEncodedString(options:) method in the style of the existing method base64EncodedString(options:).

Data conforms to the Collection protocol, therefore one can use
map() to map each byte to the corresponding hex string.
The %02x format prints the argument in base 16, filled up to two digits
with a leading zero if necessary. The hh modifier causes the argument
(which is passed as an integer on the stack) to be treated as a one byte
quantity. One could omit the modifier here because $0 is an unsigned
number (UInt8) and no sign-extension will occur, but it does no harm leaving
it in.

The result is then joined to a single string.

Example:

let data = Data([0, 1, 127, 128, 255])
// For Swift < 4.2 use:
// let data = Data(bytes: [0, 1, 127, 128, 255])
print(data.hexEncodedString()) // 00017f80ff
print(data.hexEncodedString(options: .upperCase)) // 00017F80FF

The following implementation is faster by a factor about 50
(tested with 1000 random bytes). It is inspired to
RenniePet's solution
and Nick Moore's solution, but takes advantage of
String(unsafeUninitializedCapacity:initializingUTF8With:)
which was introduced with Swift 5.3/Xcode 12 and is available on macOS 11 and iOS 14 or newer.

This method allows to create a Swift string from UTF-8 units efficiently, without unnecessary copying or reallocations.

An alternative implementation for older macOS/iOS versions is also provided.

extension Data {
struct HexEncodingOptions: OptionSet {
let rawValue: Int
static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}

func hexEncodedString(options: HexEncodingOptions = []) -> String {
let hexDigits = options.contains(.upperCase) ? "0123456789ABCDEF" : "0123456789abcdef"
if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
let utf8Digits = Array(hexDigits.utf8)
return String(unsafeUninitializedCapacity: 2 * self.count) { (ptr) -> Int in
var p = ptr.baseAddress!
for byte in self {
p[0] = utf8Digits[Int(byte / 16)]
p[1] = utf8Digits[Int(byte % 16)]
p += 2
}
return 2 * self.count
}
} else {
let utf16Digits = Array(hexDigits.utf16)
var chars: [unichar] = []
chars.reserveCapacity(2 * self.count)
for byte in self {
chars.append(utf16Digits[Int(byte / 16)])
chars.append(utf16Digits[Int(byte % 16)])
}
return String(utf16CodeUnits: chars, count: chars.count)
}
}
}

How to Save A String With Hexadecimal Encoding In Swift

What I was originally doing was:
Binary->Decimal->Hex string->Data->File

What seemed to solve my issue was to do:
Binary->UInt8 Array->Data->File

Creating Data directly from [UInt8] took care of converting it to hex, spacing, and retained the hexadecimal encoding I needed.

Hopefully that helps someone else having similar issues.

Swift native functions to have numbers as hex strings

As of Swift 2, all integer types have a constructor

init?(_ text: String, radix: Int = default)

so that both integer
to hex string and hex string to integer conversions can be done
with built-in methods. Example:

let num = 1000
let str = String(num, radix: 16)
print(str) // "3e8"

if let num2 = Int(str, radix: 16) {
print(num2) // 1000
}

(Old answer for Swift 1:) The conversion from an integer to a hex string can be done with

let hex = String(num, radix: 16)

(see for example How to convert a decimal number to binary in Swift?). This does not require the import of any Framework
and works with any base between 2 and 36.

The conversion from a hex string to an integer can be done with the BSD
library function strtoul() (compare How to convert a binary to decimal in Swift?) if you are willing to import Darwin.

Otherwise there is (as far as I know) no built-in Swift method. Here is an extension
that converts a string to a number according to a given base:

extension UInt {
init?(_ string: String, radix: UInt) {
let digits = "0123456789abcdefghijklmnopqrstuvwxyz"
var result = UInt(0)
for digit in string.lowercaseString {
if let range = digits.rangeOfString(String(digit)) {
let val = UInt(distance(digits.startIndex, range.startIndex))
if val >= radix {
return nil
}
result = result * radix + val
} else {
return nil
}
}
self = result
}
}

Example:

let hexString = "A0"
if let num = UInt(hexString, radix: 16) {
println(num)
} else {
println("invalid input")
}

Write Hex string to new .mid file as Binary Data

After converting the file to a string

Well don’t convert the file to a string. Use the Data struct. Read the file as Data. Examine it as Data. Manipulate it as Data. Save it as Data.

https://developer.apple.com/documentation/foundation/data



Related Topics



Leave a reply



Submit