Python有两个非常实用的库方法(binascii.a2b_hex(keyStr)和binascii.hexlify(keyBytes)),我一直在Swift中苦苦挣扎。 在Swift中是否有任何现成的解决方案? 如果没有,怎样实现它?假设所有边界和其他检查(如偶数长度密钥)都已完成。
Swift 3
中的数据没有“内置”的方法将其内容打印为十六进制字符串,也没有创建Data
值的方法从十六进制字符串中创建一个Data
值。
可以在如何在Swift中将Data转换为十六进制字符串或如何使用Swift打印类型为Data的变量的内容?或在Swift 3.0中将String转换为Data等地方找到“Data到十六进制字符串”方法。这里是第一个链接中的实现:
extension Data {
func hexEncodedString() -> String {
return map { String(format: "%02hhx", $0) }.joined()
}
}
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: UInt8) -> UInt8? {
switch(u) {
case 0x30 ... 0x39:
return u - 0x30
case 0x41 ... 0x46:
return u - 0x41 + 10
case 0x61 ... 0x66:
return u - 0x61 + 10
default:
return nil
}
}
self.init(capacity: string.utf8.count/2)
var iter = string.utf8.makeIterator()
while let c1 = iter.next() {
guard
let val1 = decodeNibble(u: c1),
let c2 = iter.next(),
let val2 = decodeNibble(u: c2)
else { return nil }
self.append(val1 << 4 + val2)
}
}
}
例子:
// 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")
}
even.toggle()
调用。 - Leo Dabusval1 << 4 + val2
而不是val1 << 8 + val2
。顺便问一下,为什么不像我一样将初始化器设置为通用的呢?这将允许您初始化Data以及字节数组。使用Data capacity
初始化器是否比在初始化emptyCollection后调用reserveCapacity
有任何优势? - Leo Dabusstring.withCString(...)
。也许我有时会尝试一下。但我喜欢当前的实现,因为它相对较短,易于理解,并且在我的(少量)测试中速度相当快。 - Martin R我不是很熟悉Python以及它在转换数字时所执行的检查,但您可以扩展以下函数:
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)
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