Reputation: 23616
Is there a way to convert a hexadecimal string to base64 in Swift? For example, I would like to convert:
BA5E64C0DE
to:
ul5kwN4=
It's possible to convert a normal string to base64 by using:
let hex: String = "BA5E64C0DE"
let utf8str: NSData = hex.dataUsingEncoding(NSUTF8StringEncoding)!
let base64Encoded: NSString = utf8str.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let base64: String = (base64Encoded as String)
But this would give a result of:
QkE1RTY0QzBERQ==
Because it's just treating the hex as a normal UTF-8 String, and not hexadecimal.
It's possible to convert it to base64 correctly by looping through every six hex characters and converting it to it's four respective base64 characters, but this would be highly inefficient, and is just plain stupid (there would need to be 17,830,160 if statements):
if(hex == "000000"){base64+="AAAA"}
else if(hex == "000001"){base64+="AAAB"}
else if(hex == "000002"){base64+="AAAC"}
else if(hex == "BA5E64"){base64+="ul5k"}
//...
It would be nice if there was something like this:
let hex: String = "BA5E64C0DE"
let data: NSData = hex.dataUsingEncoding(NSHexadecimalEncoding)!
let base64Encoded: NSString = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let base64: String = (base64Encoded as String)
But sadly, there's no NSHexadecimalEncoding
. Is there any efficient way to convert a hexadecimal string to it's base64 representation in Swift?
Upvotes: 2
Views: 6435
Reputation: 7068
First, convert Hex String
to Data
using the following routine. (Worked in Swift 3.0.2)
extension String {
/// Expanded encoding
///
/// - bytesHexLiteral: Hex string of bytes
/// - base64: Base64 string
enum ExpandedEncoding {
/// Hex string of bytes
case bytesHexLiteral
/// Base64 string
case base64
}
/// Convert to `Data` with expanded encoding
///
/// - Parameter encoding: Expanded encoding
/// - Returns: data
func data(using encoding: ExpandedEncoding) -> Data? {
switch encoding {
case .bytesHexLiteral:
guard self.characters.count % 2 == 0 else { return nil }
var data = Data()
var byteLiteral = ""
for (index, character) in self.characters.enumerated() {
if index % 2 == 0 {
byteLiteral = String(character)
} else {
byteLiteral.append(character)
guard let byte = UInt8(byteLiteral, radix: 16) else { return nil }
data.append(byte)
}
}
return data
case .base64:
return Data(base64Encoded: self)
}
}
}
Then, convert Data
to Base64 String
using Data.base64EncodedString(options:)
.
Usage
let base64 = "BA5E64C0DE".data(using: .bytesHexLiteral)?.base64EncodedString()
if let base64 = base64 {
print(base64)
// Prints "ul5kwN4="
}
Upvotes: 2
Reputation: 438277
The base-64 string, "ul5kwN4="
, translates to a binary NSData
consisting of of five bytes BA
, 5E
, 64
, C0
, and DE
.
Now, if you really had a string with the hexadecimal representation, you could convert it to a binary NSData
using a routine like the one here: https://stackoverflow.com/a/26502285/1271826
Once you have a NSData
, you could build your base 64 string:
let hexString = "BA5E64C0DE"
let binaryData = hexString.dataFromHexadecimalString()
let base64String = binaryData?.base64EncodedStringWithOptions(nil)
That generates the desired output, ul5kwN4=
.
Upvotes: 6