How to convert Data to hex string in swift

前端 未结 7 2350
走了就别回头了
走了就别回头了 2020-11-22 07:59

I want the hexadecimal representation of a Data value in Swift.

Eventually I\'d want to use it like this:

let data = Data(base64Encoded: \"aGVsbG8gd2         


        
7条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-11-22 08:15

    An alternative implementation (taken from How to crypt string to sha1 with 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 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(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 120 (tested with 1000 random bytes). It is similar to RenniePet's solution and Nick Moore's solution, but based on UTF-16 code units, which is what Swift strings (currently) use as internal storage.

    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)
        }
    }
    

提交回复
热议问题