hex/binary string conversion in Swift

后端 未结 3 1545
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-27 23:38

Python has two very useful library method (binascii.a2b_hex(keyStr) and binascii.hexlify(keyBytes)) which I have been struggling with in Swift. Is there anything readily ava

相关标签:
3条回答
  • 2020-11-28 00:26

    Not really familiar with Python and the checks it performs when convert the numbers, but you can expand the function below:

    func convert(_ str: String, fromRadix r1: Int, toRadix r2: Int) -> String? {
        if let num = Int(str, radix: r1) {
            return String(num, radix: r2)
        } else {
            return nil
        }
    }
    
    convert("11111111", fromRadix: 2, toRadix: 16)
    convert("ff", fromRadix: 16, toRadix: 2)
    
    0 讨论(0)
  • 2020-11-28 00:28

    Data from Swift 3 has no "built-in" method to print its contents as a hex string, or to create a Data value from a hex string.

    "Data to hex string" methods can be found e.g. at How to convert Data to hex string in swift or How to print the content of a variable type Data using swift? or converting string to data in swift 3.0. Here is an implementation from the first link:

    extension Data {
        func hexEncodedString() -> String {
            return map { String(format: "%02hhx", $0) }.joined()
        }
    }
    

    Here is a possible implementation of the reverse "hex string to Data" conversion (taken from Hex String to Bytes (NSData) on Code Review, translated to Swift 3 and improved) as a failable inititializer:

    extension Data {
    
        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 }
        }
    }
    

    Example:

    // Hex string to Data:
    if let data = Data(fromHexEncodedString: "0002468A13579BFF") {
        let idata = Data(data.map { 255 - $0 })
    
        // Data to hex string:
        print(idata.hexEncodedString()) // fffdb975eca86400
    } else {
        print("invalid hex string")
    }
    
    0 讨论(0)
  • 2020-11-28 00:31

    Swift 2

    extension NSData {
        class func dataFromHexString(hex: String) -> NSData? {
            let regex = try! NSRegularExpression(pattern: "^[0-9a-zA-Z]*$", options: .CaseInsensitive)
            let validate = regex.firstMatchInString(hex, options: NSMatchingOptions.init(rawValue: 0), range: NSRange(location: 0, length: hex.characters.count))
            if validate == nil || hex.characters.count % 2 != 0 {
                return nil
            }
            let data = NSMutableData()
            for i in 0..<hex.characters.count/2 {
                let hexStr = hex.substring(i * 2, length: 2)
                var ch: UInt32 = 0
                NSScanner(string: hexStr).scanHexInt(&ch)
                data.appendBytes(&ch, length: 1)
            }
            return data
        }
    }
    
    let a = 0xabcd1234
    print(String(format: "%x", a)) // Hex to String
    NSData.dataFromHexString("abcd1234") // String to hex
    
    0 讨论(0)
提交回复
热议问题