在 Swift 中将十六进制字符串转换为 Base64

Convert Hexadecimal String to Base64 in Swift

在Swift中有没有办法将十六进制字符串转换为base64?例如,我想转换:

BA5E64C0DE

至:

ul5kwN4=

可以使用以下方法将普通字符串转换为 base64:

let hex: String = "BA5E64C0DE"

let utf8str: NSData = hex.dataUsingEncoding(NSUTF8StringEncoding)!
let base64Encoded: NSString = utf8str.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))

let base64: String = (base64Encoded as String)

但这会产生以下结果:

QkE1RTY0QzBERQ==

因为它只是将十六进制视为普通的 UTF-8 字符串,而不是十六进制。

通过循环遍历每六个十六进制字符并将其转换为四个相应的 base64 字符,可以将其正确转换为 base64,但这将是非常低效的,而且非常愚蠢(需要 17,830,160 if 语句):

if(hex == "000000"){base64+="AAAA"}
else if(hex == "000001"){base64+="AAAB"}
else if(hex == "000002"){base64+="AAAC"}
else if(hex == "BA5E64"){base64+="ul5k"}
//...

如果有这样的就好了:

let hex: String = "BA5E64C0DE"

let data: NSData = hex.dataUsingEncoding(NSHexadecimalEncoding)!
let base64Encoded: NSString = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))

let base64: String = (base64Encoded as String)

但遗憾的是,没有 NSHexadecimalEncoding。有什么有效的方法可以将十六进制字符串转换为 Swift 中的 base64 表示形式?

base-64 字符串 "ul5kwN4=" 转换为由五个字节组成的二进制 NSData BA5E64C0, 和 DE.

现在,如果您确实有一个十六进制表示的字符串,您可以使用此处的例程将其转换为二进制 NSData

一旦你有了 NSData,你就可以构建你的 base 64 字符串:

let hexString = "BA5E64C0DE"
let binaryData = hexString.dataFromHexadecimalString()
let base64String = binaryData?.base64EncodedStringWithOptions(nil)

生成所需的输出,ul5kwN4=

  1. 首先,使用以下例程将Hex String转换为Data。 (在 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)
            }
        }
    }
    
  2. 然后,使用Data.base64EncodedString(options:)Data转换为Base64 String


用法

let base64 = "BA5E64C0DE".data(using: .bytesHexLiteral)?.base64EncodedString()
if let base64 = base64 {
    print(base64)
    // Prints "ul5kwN4="
}