Swift 4 hex string to binary string - swift

Noted that the old method to convert a hex string to a binary string has been removed from swift i.e. : String(hex, radix: 2) -> binary string
What is an alternative in swift 4?

You need first to convert your hexaString to an Array of Bytes [UInt8]. Then you can use String(_, radix:) to convert the bytes to binary. Note that if you would like to return a String instead of an array of strings [String] you would need to add leading zeros to make your binary strings length consistent (8 characters):
extension String {
typealias Byte = UInt8
var hexaToBytes: [Byte] {
var start = startIndex
return stride(from: 0, to: count, by: 2).compactMap { _ in // use flatMap for older Swift versions
let end = index(after: start)
defer { start = index(after: end) }
return Byte(self[start...end], radix: 16)
}
}
var hexaToBinary: String {
return hexaToBytes.map {
let binary = String($0, radix: 2)
return repeatElement("0", count: 8-binary.count) + binary
}.joined()
}
}
let hexString = "00ff01fe"
hexString.hexaToBinary // "00000000111111110000000111111110"

I don't recall any function that would convert a hex string to another string of arbitrary radix. Perhaps you are thinking about the initializer functions that convert between strings and integer values (and vice versa) using an arbitrary radix:
let hex = "00ff01fe"
let value = UInt64(hex, radix: 16)!
let binary = String(value, radix: 2)
let paddedBinary = repeatElement("0", count: 64 - binary.count) + binary
But that only applies when the hex string represents a 64 bit value, but it illustrates the basic idea. Convert to some integer type, and then convert back to binary, padding it out with zeros.
If you have a hex string that is longer than that, you cannot use the above. But you can map the individual characters of your hex string to numeric values, build binary representation of each, zero pad them, and use joined to concatenate them together:
let hex = "ffeeddccbbaa99887766554433221100"
let result = hex.compactMap { c -> String? in
guard let value = Int(String(c), radix: 16) else { return nil }
let string = String(value, radix: 2)
return repeatElement("0", count: 4 - string.count) + string
}.joined()

Related

How I can convert int to binary string swift?

I have such int number:
266
I would like to convert it to binary string. In android I use such method:
Integer.toBinaryString(266)
and the output was:
000100001010
I ios I tried to use string with radix:
String(266, radix: 2)
but I got:
100001010
I found such question-answer and used such code:
func pad(string : String, toSize: Int) -> String {
var padded = string
for _ in 0..<(toSize - string.count) {
padded = "0" + padded
}
return padded
}
and:
pad(string: String(ResumeController.userData.edu!), toSize: 12)
and got:
000100001010
can you please explain why external function which added some 0s works similar to the kotlin one which is built-in? And also one more question - how I can get this number back from this binary string?
There is a function that can convert to integer Int("000100001010", radix: 2)
To append zeroes, use this:
let str = String(repeating: "0", count: amount)

How to convert my bytes data to Hex String and then Signed integer (32-bit) Two's complement from that ..?

I have a data like a bellow:
let data = Data(bytes: [206, 66, 49, 62])
Then I used this extension (from How to convert Data to hex string in swift) to convert to a hex string:
extension Data {
struct HexEncodingOptions: OptionSet {
let rawValue: Int
static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}
func hexEncodedString(options: HexEncodingOptions = []) -> String {
let hexDigits = Array((options.contains(.upperCase) ? "0123456789ABCDEF" : "0123456789abcdef").utf16)
var chars: [unichar] = []
chars.reserveCapacity(2 * count)
for byte in self {
chars.append(hexDigits[Int(byte / 16)])
chars.append(hexDigits[Int(byte % 16)])
}
return String(utf16CodeUnits: chars, count: chars.count)
}
}
And then it is giving "ce42313e" as hex string. Now I am trying to convert this to Signed integer (32-bit) Two's complement .. I tried a couple of ways but not find anything perfectly.
When I give "ce42313e" in this bellow link under hex decimal the value is -834522818
http://www.binaryconvert.com/convert_signed_int.html
bellow is one of those I tried to convert "ce42313e" to int and it's giving me 3460444478 ..instead of -834522818 .
let str = value
let number = Int(str, radix: 16)
Please help out to get that value.
Int(str, radix: 16) interprets the string as the hexadecimal
representation of an unsigned number. You could convert it to
Int32 with
let data = Data(bytes: [206, 66, 49, 62])
let str = data.hexEncodedString()
print(str) // ce42313e
let number = Int32(truncatingBitPattern: Int(str, radix: 16)!)
print(number) // -834522818
But actually you don't need the hex representation for that purpose.
Your data is the big-endian representation of a signed 32-bit integer,
and this is how you can get the number from the data directly:
let data = Data(bytes: [206, 66, 49, 62])
let number = Int32(bigEndian: data.withUnsafeBytes { $0.pointee })
print(number) // -834522818

Convert hex-encoded String to String

I want to convert following hex-encoded String in Swift 3:
dcb04a9e103a5cd8b53763051cef09bc66abe029fdebae5e1d417e2ffc2a07a4
to its equivalant String:
Ü°J:\ص7cï ¼f«à)ýë®^A~/ü*¤
Following websites do the job very fine:
http://codebeautify.org/hex-string-converter
http://string-functions.com/hex-string.aspx
But I am unable to do the same in Swift 3. Following code doesn't do the job too:
func convertHexStringToNormalString(hexString:String)->String!{
if let data = hexString.data(using: .utf8){
return String.init(data:data, encoding: .utf8)
}else{ return nil}
}
Your code doesn't do what you think it does. This line:
if let data = hexString.data(using: .utf8){
means "encode these characters into UTF-8." That means that "01" doesn't encode to 0x01 (1), it encodes to 0x30 0x31 ("0" "1"). There's no "hex" in there anywhere.
This line:
return String.init(data:data, encoding: .utf8)
just takes the encoded UTF-8 data, interprets it as UTF-8, and returns it. These two methods are symmetrical, so you should expect this whole function to return whatever it was handed.
Pulling together Martin and Larme's comments into one place here. This appears to be encoded in Latin-1. (This is a really awkward way to encode this data, but if it's what you're looking for, I think that's the encoding.)
import Foundation
extension Data {
// From http://stackoverflow.com/a/40278391:
init?(fromHexEncodedString string: String) {
// Convert 0 ... 9, a ... f, A ...F to their decimal value,
// return nil for all other input characters
func decodeNibble(u: UInt16) -> UInt8? {
switch(u) {
case 0x30 ... 0x39:
return UInt8(u - 0x30)
case 0x41 ... 0x46:
return UInt8(u - 0x41 + 10)
case 0x61 ... 0x66:
return UInt8(u - 0x61 + 10)
default:
return nil
}
}
self.init(capacity: string.utf16.count/2)
var even = true
var byte: UInt8 = 0
for c in string.utf16 {
guard let val = decodeNibble(u: c) else { return nil }
if even {
byte = val << 4
} else {
byte += val
self.append(byte)
}
even = !even
}
guard even else { return nil }
}
}
let d = Data(fromHexEncodedString: "dcb04a9e103a5cd8b53763051cef09bc66abe029fdebae5e1d417e2ffc2a07a4")!
let s = String(data: d, encoding: .isoLatin1)
You want to use the hex encoded data as an AES key, but the
data is not a valid UTF-8 sequence. You could interpret
it as a string in ISO Latin encoding, but the AES(key: String, ...)
initializer converts the string back to its UTF-8 representation,
i.e. you'll get different key data from what you started with.
Therefore you should not convert it to a string at all. Use the
extension Data {
init?(fromHexEncodedString string: String)
}
method from hex/binary string conversion in Swift
to convert the hex encoded string to Data and then pass that
as an array to the AES(key: Array<UInt8>, ...) initializer:
let hexkey = "dcb04a9e103a5cd8b53763051cef09bc66abe029fdebae5e1d417e2ffc2a07a4"
let key = Array(Data(fromHexEncodedString: hexkey)!)
let encrypted = try AES(key: key, ....)
There is still a way to convert the key from hex to readable string by adding the below extension:
extension String {
func hexToString()->String{
var finalString = ""
let chars = Array(self)
for count in stride(from: 0, to: chars.count - 1, by: 2){
let firstDigit = Int.init("\(chars[count])", radix: 16) ?? 0
let lastDigit = Int.init("\(chars[count + 1])", radix: 16) ?? 0
let decimal = firstDigit * 16 + lastDigit
let decimalString = String(format: "%c", decimal) as String
finalString.append(Character.init(decimalString))
}
return finalString
}
func base64Decoded() -> String? {
guard let data = Data(base64Encoded: self) else { return nil }
return String(data: data, encoding: .init(rawValue: 0))
}
}
Example of use:
let hexToString = secretKey.hexToString()
let base64ReadableKey = hexToString.base64Decoded() ?? ""

How to increment a Hex number

I am looking for help to increment a hexadecimal by 1. An example of this might be "000001" or "AD02D3" and increment to "000002" or "AD02D4". I can't figure out how to do this in Swift. If I convert to an Int:
var num2 = Int(str, radix: 16)
I loose all the preceding zeros and there are difficulties converting back.
Any suggestions?
Save the string length in a variable
Convert to an integer Int(str, radix: 16)
Add 1 to the integer
Use a format string with the saved length and specifying leading "0"s
Create the new string for the format function
let str = "00000A"
let len = str.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
let num2 = Int(str, radix: 16)! + 1
let newStr = NSString(format: "%0\(len)X", num2) as String
print("newStr: \(newStr)") // newStr: 00000B
import Foundation
func inc(s: String)->String? {
if let i = Int(s,radix: 16)?.successor() {
return String(format: "%0\(s.characters.count)X", arguments: [i])
} else {
return nil
}
}
let arr0 = ["01","0000FE00","FFFFFF"]
let arr1 = arr0.flatMap{ inc($0) }
print(arr1) // ["02", "0000FE01", "1000000"]

Binary to hexadecimal in Swift

I have a string in binary (for example "00100100"), and I want it in hexadecimal (like "24").
Is there a method written to convert 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
}
let binaryInteger = 0b1
// Your binary number
let hexadecimalNum = String(binaryInteger, radix: 16)
// convert into string format in whatever base you want
For more information
let decimalInteger = 15 // prefix NONE
let binaryInteger = 0b10001 // prefix 0b
let octalInteger = 0o21 // prefix 0o
let hexadecimalInteger = 0x11 // prefix 0x