在Swift中将hexstring转换为NSData

我得到了在Objective-C中将string转换为HEX-String的代码。

- (NSString *) CreateDataWithHexString:(NSString*)inputString { NSUInteger inLength = [inputString length]; unichar *inCharacters = alloca(sizeof(unichar) * inLength); [inputString getCharacters:inCharacters range:NSMakeRange(0, inLength)]; UInt8 *outBytes = malloc(sizeof(UInt8) * ((inLength / 2) + 1)); NSInteger i, o = 0; UInt8 outByte = 0; for (i = 0; i < inLength; i++) { UInt8 c = inCharacters[i]; SInt8 value = -1; if (c >= '0' && c <= '9') value = (c - '0'); else if (c >= 'A' && c <= 'F') value = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') value = 10 + (c - 'a'); if (value >= 0) { if (i % 2 == 1) { outBytes[o++] = (outByte << 4) | value; outByte = 0; } else { outByte = value; } } else { if (o != 0) break; } } NSData *a = [[NSData alloc] initWithBytesNoCopy:outBytes length:o freeWhenDone:YES]; NSString* newStr = [NSString stringWithUTF8String:[a bytes]]; return newStr; } 

我想在Swift中一样。 任何人都可以在Swift中翻译这个代码,或者有什么简单的方法在Swift中做到这一点?

这是我的Data例程的hexstring:

 extension String { /// Create `Data` from hexadecimal string representation /// /// This takes a hexadecimal representation and creates a `Data` object. Note, if the string has any spaces or non-hex characters (eg starts with '<' and with a '>'), those are ignored and only hex characters are processed. /// /// - returns: Data represented by this hexadecimal string. func hexadecimal() -> Data? { var data = Data(capacity: characters.count / 2) let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive) regex.enumerateMatches(in: self, range: NSMakeRange(0, utf16.count)) { match, flags, stop in let byteString = (self as NSString).substring(with: match!.range) var num = UInt8(byteString, radix: 16)! data.append(&num, count: 1) } guard data.count > 0 else { return nil } return data } } 

为了完整起见,这是我的Data到hexstring例程:

 extension Data { /// Create hexadecimal string representation of `Data` object. /// /// - returns: `String` representation of this `Data` object. func hexadecimal() -> String { return map { String(format: "%02x", $0) } .joined(separator: "") } } 

请注意,如上所示,我通常只在hex表示和NSData实例之间进行转换(因为如果信息可能已经被表示为一个string,您可能不会在第一个位置创buildhex表示)。 但是你原来的问题想要在hex表示和String对象之间进行转换,而且可能如下所示:

 extension String { /// Create `String` representation of `Data` created from hexadecimal string representation /// /// This takes a hexadecimal representation and creates a String object from that. Note, if the string has any spaces, those are removed. Also if the string started with a `<` or ended with a `>`, those are removed, too. /// /// For example, /// /// String(hexadecimal: "<666f6f>") /// /// is /// /// Optional("foo") /// /// - returns: `String` represented by this hexadecimal string. init?(hexadecimal string: String, encoding: String.Encoding = .utf8) { guard let data = string.hexadecimal() else { return nil } self.init(data: data, encoding: encoding) } /// Create hexadecimal string representation of `String` object. /// /// For example, /// /// "foo".hexadecimalString() /// /// is /// /// Optional("666f6f") /// /// - parameter encoding: The `String.Encoding` that indicates how the string should be converted to `Data` before performing the hexadecimal conversion. /// /// - returns: `String` representation of this String object. func hexadecimalString(encoding: String.Encoding = .utf8) -> String? { return data(using: encoding)? .hexadecimal() } } 

然后你可以像上面这样使用上面的代码:

 let hexString = "68656c6c 6f2c2077 6f726c64" print(String(hexadecimal: hexString)) 

要么,

 let originalString = "hello, world" print(originalString.hexadecimalString()) 

对于早期Swift版本的上述排列,请参阅此问题的修订历史logging。

将hexstring转换为数据和字符

SWIFT1

 func dataWithHexString(hex: String) -> NSData { var hex = hex let data = NSMutableData() while(countElements(hex) > 0) { var c: String = hex.substringToIndex(advance(hex.startIndex, 2)) hex = hex.substringFromIndex(advance(hex.startIndex, 2)) var ch: UInt32 = 0 NSScanner(string: c).scanHexInt(&ch) data.appendBytes(&ch, length: 1) } return data } 

使用:

 let data = dataWithHexString("68656c6c6f2c20776f726c64") // <68656c6c 6f2c2077 6f726c64> if let string = NSString(data: data, encoding: 1) { print(string) // hello, world } 

Swift2

 func dataWithHexString(hex: String) -> NSData { var hex = hex let data = NSMutableData() while(hex.characters.count > 0) { let c: String = hex.substringToIndex(hex.startIndex.advancedBy(2)) hex = hex.substringFromIndex(hex.startIndex.advancedBy(2)) var ch: UInt32 = 0 NSScanner(string: c).scanHexInt(&ch) data.appendBytes(&ch, length: 1) } return data } 

使用:

 let data = dataWithHexString("68656c6c6f2c20776f726c64") // <68656c6c 6f2c2077 6f726c64> if let string = String(data: data, encoding: NSUTF8StringEncoding) { print(string) //"hello, world" } 

Swift3

 func dataWithHexString(hex: String) -> Data { var hex = hex var data = Data() while(hex.characters.count > 0) { let c: String = hex.substring(to: hex.index(hex.startIndex, offsetBy: 2)) hex = hex.substring(from: hex.index(hex.startIndex, offsetBy: 2)) var ch: UInt32 = 0 Scanner(string: c).scanHexInt32(&ch) var char = UInt8(ch) data.append(&char, count: 1) } return data } 

使用:

 let data = dataWithHexString(hex: "68656c6c6f2c20776f726c64") // <68656c6c 6f2c2077 6f726c64> let string = String(data: data, encoding: .utf8) // "hello, world" 

Swift 4实现:

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

用法:

 let data = Data(hexString: "0a1b3c4d") 

这是我解决的一个简单的解决scheme:

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

用法:

 let data = NSData(hexString: "b8dfb080bc33fb564249e34252bf143d88fc018f") 

输出:

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

更新6/29/2016

我更新了初始化程序来处理格式不正确的数据(即无效字符或奇数字符)。

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

代码在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) } } } 

Rob的代码唯一需要的是:

 extension NSData { func toHexString() -> String { var string = NSMutableString(capacity: length * 2) var byte: UInt8 = 0 for i in 0 ..< length { getBytes(&byte, range: NSMakeRange(i, 1)) string.appendFormat("%02x", byte) } return string as String } } 

然后做

 yourdataobject.toHexString() 

获取二进制数据作为hexstring。 假设你的数据对象是NSDatatypes的。