[FIXED] Konvertieren von Hex-String in NSData in Swift

Ausgabe

Ich habe den Code zum Konvertieren von String in HEX-String in 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;
}

Ich möchte das gleiche in Swift. Kann jemand diesen Code in Swift übersetzen, oder gibt es eine einfache Möglichkeit, dies in Swift zu tun?

Lösung

Dies ist mein Hex-String zur DataRoutine:

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

Und der Vollständigkeit halber ist dies meine Datato hex string-Routine:

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

Beachten Sie, wie oben gezeigt, dass ich im Allgemeinen nur zwischen hexadezimalen Darstellungen und NSDataInstanzen konvertiere (denn wenn die Informationen als Zeichenfolge hätten dargestellt werden können, hätten Sie wahrscheinlich überhaupt keine hexadezimale Darstellung erstellt). Aber Ihre ursprüngliche Frage wollte zwischen hexadezimalen Darstellungen und StringObjekten konvertieren, und das könnte so aussehen:

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

Sie könnten dann das obige wie folgt verwenden:

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

Oder,

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

Permutationen des Obigen für frühere Swift-Versionen finden Sie im Revisionsverlauf dieser Frage.


Beantwortet von –
Rob


Antwort geprüft von –
Cary Denson (FixError Admin)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like