如何在 Swift 3 中将 HexString 转换为 ByteArray

问题描述 投票:0回答:5

我正在尝试将 hexString 转换为字节数组([UInt8]) 我到处搜索但找不到解决方案。下面是我的 swift 2 代码

func stringToBytes(_ string: String) -> [UInt8]? {
    let chars = Array(string)
    let length = chars.count
    if length & 1 != 0 {
        return nil
    }
    var bytes = [UInt8]()
    bytes.reserveCapacity(length/2)
    for var i = 0; i < length; i += 2 {
        if let a = find(hexChars, chars[i]),
            let b = find(hexChars, chars[i+1]) {
            bytes.append(UInt8(a << 4) + UInt8(b))
        } else {
            return nil
        }
    }
    return bytes
} 

十六进制示例

十六进制:“7661706f72”

预期输出:“蒸气”

swift swift3 byte
5个回答
24
投票

此代码可以生成与您的 swift 2 代码相同的输出。

func stringToBytes(_ string: String) -> [UInt8]? {
    // let length = string.characters.count
    // Updating / replacing previous (now commented) line for Swift 5 (2023-12)
    // No longer need reference characters.
    let length = string.count
    if length & 1 != 0 {
        return nil
    }
    var bytes = [UInt8]()
    bytes.reserveCapacity(length/2)
    var index = string.startIndex
    for _ in 0..<length/2 {
        let nextIndex = string.index(index, offsetBy: 2)
        if let b = UInt8(string[index..<nextIndex], radix: 16) {
            bytes.append(b)
        } else {
            return nil
        }
        index = nextIndex
    }
    return bytes
}

let bytes = stringToBytes("7661706f72")
print(String(bytes: bytes!, encoding: .utf8)) //->Optional("vapor")

4
投票

这是我如何以更惯用的 Swift 风格进行操作的草图(这可能仅限于 Swift 4):

func toPairsOfChars(pairs: [String], string: String) -> [String] { 
    if string.count == 0 {
        return pairs
    } 
    var pairsMod = pairs
    pairsMod.append(String(string.prefix(2))) 
    return toPairsOfChars(pairs: pairsMod, string: String(string.dropFirst(2))) 
}

func stringToBytes(_ string: String) -> [UInt8]? {
    // omit error checking: remove '0x', make sure even, valid chars
    let pairs = toPairsOfChars(pairs: [], string: string)
    return pairs.map { UInt8($0, radix: 16)! }
}

3
投票

以下代码可能对您有帮助

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 (e.g. 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, options: [], range: NSMakeRange(0, characters.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
 }
}

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.

init?(hexadecimal string: String) {
    guard let data = string.hexadecimal() else {
        return nil
    }

    self.init(data: data, encoding: .utf8)
}

/// - parameter encoding: The `NSStringCoding` that indicates how the string should be converted to `NSData` before performing the hexadecimal conversion.

/// - returns: `String` representation of this String object.

func hexadecimalString() -> String? {
    return data(using: .utf8)?
        .hexadecimal()
}

 }

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

像这样使用:

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

或者

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

2
投票

经过大量搜索和思考,这就是你的做法

func toByteArray( _ hex:String ) -> [UInt8] {

    // remove "-" from Hexadecimal
    var hexString = hex.removeWord( "-" )

    let size = hexString.characters.count / 2
    var result:[UInt8] = [UInt8]( repeating: 0, count: size ) // array with length = size

    // for ( int i = 0; i < hexString.length; i += 2 )
    for i in stride( from: 0, to: hexString.characters.count, by: 2 ) {

        let subHexStr = hexString.subString( i, length: 2 )

        result[ i / 2 ] = UInt8( subHexStr, radix: 16 )! // ! - because could be null
    }

    return result
}


extension String {

    func subString( _ from: Int, length: Int ) -> String {

        let size = self.characters.count

        let to = length + from
        if from < 0 || to > size {

            return ""
        }

        var result = ""

        for ( idx, char ) in self.characters.enumerated() {

            if idx >= from && idx < to {

                result.append( char )
            }
        }

        return result
    }

    func removeWord( _ word:String ) -> String {

        var result = ""

        let textCharArr = Array( self.characters )
        let wordCharArr = Array( word.characters )

        var possibleMatch = ""

        var i = 0, j = 0
        while i < textCharArr.count {

            if textCharArr[ i ] == wordCharArr[ j ] {

                if j == wordCharArr.count - 1 {

                    possibleMatch = ""
                    j = 0
                }
                else {

                    possibleMatch.append( textCharArr[ i ] )
                    j += 1
                }
            }
            else {

                result.append( possibleMatch ) 
                possibleMatch = ""

                if j == 0 {

                    result.append( textCharArr[ i ] )
                }
                else {

                    j = 0
                    i -= 1
                }
            }

            i += 1
        }

        return result
    }   
}

请参阅此视频了解我是如何做到的。 信用:AllTech


1
投票

使用更好的语法将字符串转换为数据。

static func hexStringToData(string: String) -> Data {
    let stringArray = Array(string)
    var data: Data = Data()
    for i in stride(from: 0, to: string.count, by: 2) {
        let pair: String = String(stringArray[i]) + String(stringArray[i+1])
        if let byteNum = UInt8(pair, radix: 16) {
            let byte = Data([byteNum])
            data.append(byte)
        }
        else{
            fatalError()
        }
    }
    return data
}
© www.soinside.com 2019 - 2024. All rights reserved.