Converting Hex String to NSData in Swift

后端 未结 11 1105
一生所求
一生所求 2020-11-27 05:22

I got the code to convert String to HEX-String in objective-C.

- (NSString *) CreateDataWithHexString:(NSString*)inputString
{
NSUInteger inLength = [inputSt         


        
相关标签:
11条回答
  • 2020-11-27 05:54

    Swift 5

    With support iOS 13 and iOS2...iOS12.

    extension String {
      var hex: Data? {
        var value = self
        var data = Data()
        
        while value.count > 0 {
          let subIndex = value.index(value.startIndex, offsetBy: 2)
          let c = String(value[..<subIndex])
          value = String(value[subIndex...])
          
          var char: UInt8
          if #available(iOS 13.0, *) {
            guard let int = Scanner(string: c).scanInt32(representation: .hexadecimal) else { return nil }
            char = UInt8(int)
          } else {
            var int: UInt32 = 0
            Scanner(string: c).scanHexInt32(&int)
            char = UInt8(int)
          }
          
          data.append(&char, count: 1)
        }
        
        return data
      }
    }
    
    0 讨论(0)
  • 2020-11-27 05:55

    Swift 5

    extension Data {
        init?(hex: String) {
            guard hex.count.isMultiple(of: 2) else {
                return nil
            }
            
            let chars = hex.map { $0 }
            let bytes = stride(from: 0, to: chars.count, by: 2)
                .map { String(chars[$0]) + String(chars[$0 + 1]) }
                .compactMap { UInt8($0, radix: 16) }
            
            guard hex.count / bytes.count == 2 else { return nil }
            self.init(bytes)
        }
    }
    
    0 讨论(0)
  • 2020-11-27 05:57

    Swift 4 & Swift 5 implementation:

    init?(hexString: String) {
      let len = hexString.count / 2
      var data = Data(capacity: len)
      var i = hexString.startIndex
      for _ in 0..<len {
        let j = hexString.index(i, offsetBy: 2)
        let bytes = hexString[i..<j]
        if var num = UInt8(bytes, radix: 16) {
          data.append(&num, count: 1)
        } else {
          return nil
        }
        i = j
      }
      self = data
    }
    

    Usage:

    let data = Data(hexString: "0a1b3c4d")
    
    0 讨论(0)
  • 2020-11-27 06:03

    Here's a simple solution I settled on:

    extension NSData {
        public convenience init(hexString: String) {
            var index = hexString.startIndex
            var bytes: [UInt8] = []
            repeat {
                bytes.append(hexString[index...index.advancedBy(1)].withCString {
                    return UInt8(strtoul($0, nil, 16))
                })
    
                index = index.advancedBy(2)
            } while index.distanceTo(hexString.endIndex) != 0
    
            self.init(bytes: &bytes, length: bytes.count)
        }
    }
    

    Usage:

    let data = NSData(hexString: "b8dfb080bc33fb564249e34252bf143d88fc018f")
    

    Output:

    print(data)
    >>> <b8dfb080 bc33fb56 4249e342 52bf143d 88fc018f>
    

    Update 6/29/2016

    I updated the initializer to handle malformed data (i.e., invalid characters or odd number of characters).

    public convenience init?(hexString: String, force: Bool) {
        let characterSet = NSCharacterSet(charactersInString: "0123456789abcdefABCDEF")
        for scalar in hexString.unicodeScalars {
            if characterSet.characterIsMember(UInt16(scalar.value)) {
                hexString.append(scalar)
            }
            else if !force {
                return nil
            }
        }
    
        if hexString.characters.count % 2 == 1 {
            if force {
                hexString = "0" + hexString
            }
            else {
                return nil
            }
        }
    
        var index = hexString.startIndex
        var bytes: [UInt8] = []
        repeat {
            bytes.append(hexString[index...index.advancedBy(1)].withCString {
                return UInt8(strtoul($0, nil, 16))
                })
    
            index = index.advancedBy(2)
        } while index.distanceTo(hexString.endIndex) != 0
    
        self.init(bytes: &bytes, length: bytes.count)
    }
    
    0 讨论(0)
  • 2020-11-27 06:03

    Here is my take on converting hexadecimal string to Data using Swift 4:

    extension Data {
        private static let hexRegex = try! NSRegularExpression(pattern: "^([a-fA-F0-9][a-fA-F0-9])*$", options: [])
    
        init?(hexString: String) {
            if Data.hexRegex.matches(in: hexString, range: NSMakeRange(0, hexString.count)).isEmpty {
                return nil // does not look like a hexadecimal string
            }
    
            let chars = Array(hexString)
    
            let bytes: [UInt8] = 
                stride(from: 0, to: chars.count, by: 2)
                    .map {UInt8(String([chars[$0], chars[$0+1]]), radix: 16)}
                    .compactMap{$0}
    
            self = Data(bytes)
        }
    
        var hexString: String {
            return map { String(format: "%02hhx", $0) }.joined()
        }
    }
    

    (I threw in a small feature for converting back to hex string I found in this answer)

    And here is how you would use it:

        let data = Data(hexString: "cafecafe")
    
        print(data?.hexString) // will print Optional("cafecafe")
    
    0 讨论(0)
提交回复
热议问题