ios - 在 Swift 中将十六进制字符串转换为 NSData

标签 ios objective-c swift

我得到了在 Objective-C 中将字符串转换为十六进制字符串的代码:

- (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 例程的十六进制字符串:

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

为了完整起见,这是我的数据到十六进制字符串例程:

extension Data {
    
    /// Hexadecimal string representation of `Data` object.
    
    var hexadecimal: String {
        return map { String(format: "%02x", $0) }
            .joined()
    }
}
<小时/>

请注意,如上所示,我通常只在十六进制表示形式和 NSData 实例之间进行转换(因为如果信息可以表示为字符串,您可能不会创建十六进制表示形式首先)。但是您最初的问题想要在十六进制表示形式和 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 版本的上述排列,请参阅此问题的修订历史记录。

关于ios - 在 Swift 中将十六进制字符串转换为 NSData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41386140/

相关文章:

ios - 将文本从 View 中的 TextLabel 传递到另一个 View 中的标签

objective-c - UINavigationController 后退按钮按下并 viewWillDisappear

ios - 如何以编程方式设置 ImageView 的方向

swift - 我无法在 Swift 3 中使用计时器更改 label.text

iphone - 协议(protocol)和委托(delegate)不能正常工作

ios - 如何访问我的应用程序的派生数据文件夹本身?

ios - 使用 SQLite 保存 map 数据

objective-c - SMLoginItemSetEnabled(...) GET 对应项

ios - 使用选项卡 View Controller 的演练

ios - 如何检索另一个 firebase 子项中的子项(数组)