如何在swift中将数据转换为十六进制字符串

如何在swift中将数据转换为十六进制字符串,swift,swift3,Swift,Swift3,我想要Swift中数据值的十六进制表示 最终,我想这样使用它: let data = Data(base64Encoded: "aGVsbG8gd29ybGQ=")! print(data.hexString) 此代码使用计算属性扩展数据类型。它遍历数据字节,并将字节的十六进制表示形式连接到结果: extension Data { var hexDescription: String { return reduce("") {$0 + String(format: "%

我想要Swift中数据值的十六进制表示

最终,我想这样使用它:

let data = Data(base64Encoded: "aGVsbG8gd29ybGQ=")!
print(data.hexString)

此代码使用计算属性扩展
数据
类型。它遍历数据字节,并将字节的十六进制表示形式连接到结果:

extension Data {
    var hexDescription: String {
        return reduce("") {$0 + String(format: "%02x", $1)}
    }
}

此代码使用计算属性扩展
数据
类型。它遍历数据字节,并将字节的十六进制表示形式连接到结果:

extension Data {
    var hexDescription: String {
        return reduce("") {$0 + String(format: "%02x", $1)}
    }
}
一个简单的实现(取自,带有大写输出的附加选项)是


下面的实现速度快了大约50倍 (使用1000个随机字节进行测试)。它的灵感来自于 而且,但是利用 它是随Swift 5.3/Xcode 12推出的,可在macOS 11和iOS 14或更高版本上使用

此方法允许高效地从UTF-8单元创建Swift字符串,而无需进行不必要的复制或重新分配

此外,还提供了适用于较旧macOS/iOS版本的替代实现

extension Data {
    struct HexEncodingOptions: OptionSet {
        let rawValue: Int
        static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
    }

    func hexEncodedString(options: HexEncodingOptions = []) -> String {
        let hexDigits = options.contains(.upperCase) ? "0123456789ABCDEF" : "0123456789abcdef"
        if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
            let utf8Digits = Array(hexDigits.utf8)
            return String(unsafeUninitializedCapacity: 2 * self.count) { (ptr) -> Int in
                var p = ptr.baseAddress!
                for byte in self {
                    p[0] = utf8Digits[Int(byte / 16)]
                    p[1] = utf8Digits[Int(byte % 16)]
                    p += 2
                }
                return 2 * self.count
            }
        } else {
            let utf16Digits = Array(hexDigits.utf16)
            var chars: [unichar] = []
            chars.reserveCapacity(2 * self.count)
            for byte in self {
                chars.append(utf16Digits[Int(byte / 16)])
                chars.append(utf16Digits[Int(byte % 16)])
            }
            return String(utf16CodeUnits: chars, count: chars.count)
        }
    }
}
扩展数据{
结构HexEncodingOptions:OptionSet{
让rawValue:Int
静态let大写=HexEncodingOptions(原始值:1字符串{
让hextdigits=options.contains(.大写)?“0123456789ABCDEF”:“0123456789ABCDEF”
如果可用(macOS 11.0、iOS 14.0、watchOS 7.0、tvOS 14.0、*){
让utf8Digits=数组(hextdigits.utf8)
返回字符串(unsafeUninitializedCapacity:2*self.count){(ptr)->Int in
var p=ptr.baseAddress!
对于自身中的字节{
p[0]=UTF8位[Int(字节/16)]
p[1]=utf8位[Int(字节%16)]
p+=2
}
返回2*self.count
}
}否则{
让utf16Digits=数组(hextdigits.utf16)
变量字符:[unichar]=[]
字符保留容量(2*自计数)
对于自身中的字节{
字符追加(UTF16位[Int(字节/16)])
字符追加(UTF16位[Int(字节%16)])
}
返回字符串(utf16CodeUnits:chars,count:chars.count)
}
}
}
一个简单的实现(取自,带有大写输出的附加选项)是


下面的实现速度快了大约50倍 (使用1000个随机字节进行测试)。它的灵感来自 而且,但是利用 它是随Swift 5.3/Xcode 12推出的,可在macOS 11和iOS 14或更高版本上使用

此方法允许高效地从UTF-8单元创建Swift字符串,而无需进行不必要的复制或重新分配

此外,还提供了适用于较旧macOS/iOS版本的替代实现

extension Data {
    struct HexEncodingOptions: OptionSet {
        let rawValue: Int
        static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
    }

    func hexEncodedString(options: HexEncodingOptions = []) -> String {
        let hexDigits = options.contains(.upperCase) ? "0123456789ABCDEF" : "0123456789abcdef"
        if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
            let utf8Digits = Array(hexDigits.utf8)
            return String(unsafeUninitializedCapacity: 2 * self.count) { (ptr) -> Int in
                var p = ptr.baseAddress!
                for byte in self {
                    p[0] = utf8Digits[Int(byte / 16)]
                    p[1] = utf8Digits[Int(byte % 16)]
                    p += 2
                }
                return 2 * self.count
            }
        } else {
            let utf16Digits = Array(hexDigits.utf16)
            var chars: [unichar] = []
            chars.reserveCapacity(2 * self.count)
            for byte in self {
                chars.append(utf16Digits[Int(byte / 16)])
                chars.append(utf16Digits[Int(byte % 16)])
            }
            return String(utf16CodeUnits: chars, count: chars.count)
        }
    }
}
扩展数据{
结构HexEncodingOptions:OptionSet{
让rawValue:Int
静态let大写=HexEncodingOptions(原始值:1字符串{
让hextdigits=options.contains(.大写)?“0123456789ABCDEF”:“0123456789ABCDEF”
如果可用(macOS 11.0、iOS 14.0、watchOS 7.0、tvOS 14.0、*){
让utf8Digits=数组(hextdigits.utf8)
返回字符串(unsafeUninitializedCapacity:2*self.count){(ptr)->Int in
var p=ptr.baseAddress!
对于自身中的字节{
p[0]=UTF8位[Int(字节/16)]
p[1]=utf8位[Int(字节%16)]
p+=2
}
返回2*self.count
}
}否则{
让utf16Digits=数组(hextdigits.utf16)
变量字符:[unichar]=[]
字符保留容量(2*自计数)
对于自身中的字节{
字符追加(UTF16位[Int(字节/16)])
字符追加(UTF16位[Int(字节%16)])
}
返回字符串(utf16CodeUnits:chars,count:chars.count)
}
}
}

这并没有真正回答OP的问题,因为它工作在Swift字节数组上,而不是数据对象上。它比其他答案大得多。但它应该更有效,因为它避免使用字符串(格式:)

无论如何,希望有人能发现这有用

public class StringMisc {

   // MARK: - Constants

   // This is used by the byteArrayToHexString() method
   private static let CHexLookup : [Character] =
      [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" ]


   // Mark: - Public methods

   /// Method to convert a byte array into a string containing hex characters, without any
   /// additional formatting.
   public static func byteArrayToHexString(_ byteArray : [UInt8]) -> String {

      var stringToReturn = ""

      for oneByte in byteArray {
         let asInt = Int(oneByte)
         stringToReturn.append(StringMisc.CHexLookup[asInt >> 4])
         stringToReturn.append(StringMisc.CHexLookup[asInt & 0x0f])
      }
      return stringToReturn
   }
}
测试用例:

  // Test the byteArrayToHexString() method
  let byteArray : [UInt8] = [ 0x25, 0x99, 0xf3 ]
  assert(StringMisc.byteArrayToHexString(byteArray) == "2599F3")

这并不能真正回答OP的问题,因为它工作在一个Swift字节数组上,而不是一个数据对象。它比其他答案大得多。但它应该更有效,因为它避免使用字符串(格式:)

无论如何,希望有人能发现这有用

public class StringMisc {

   // MARK: - Constants

   // This is used by the byteArrayToHexString() method
   private static let CHexLookup : [Character] =
      [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" ]


   // Mark: - Public methods

   /// Method to convert a byte array into a string containing hex characters, without any
   /// additional formatting.
   public static func byteArrayToHexString(_ byteArray : [UInt8]) -> String {

      var stringToReturn = ""

      for oneByte in byteArray {
         let asInt = Int(oneByte)
         stringToReturn.append(StringMisc.CHexLookup[asInt >> 4])
         stringToReturn.append(StringMisc.CHexLookup[asInt & 0x0f])
      }
      return stringToReturn
   }
}
测试用例:

  // Test the byteArrayToHexString() method
  let byteArray : [UInt8] = [ 0x25, 0x99, 0xf3 ]
  assert(StringMisc.byteArrayToHexString(byteArray) == "2599F3")

我的版本。它比Martin R.接受的[原始]答案快10倍左右

公共扩展数据{
私有静态let hexAlphabet=Array(“0123456789abcdef”.unicodeScalars)
func hexStringEncoded()->String{
字符串(减少为:“.unicodeScalars){结果,值为
result.append(Self.hexAlphabet[Int(value/0x10)])
result.append(Self.hexAlphabet[Int(值%0x10)])
})
}
}

我的版本。它比Martin R.接受的[原始]答案快10倍左右

公共扩展数据{
私有静态let hexAlphabet=Array(“0123456789abcdef”.unicodeScalars)
func hexStringEncoded()->String{
字符串(减少为:“.unicodeScalars){结果,值为
result.append(Self.hexAlphabet[Int(value/0x10)])
result.append(Self.hexAlphabet[Int(值%0x10)])
})
}
}

Swift 4-从数据到十六进制字符串
基于,但甚至更快一点

extension Data {
  /// A hexadecimal string representation of the bytes.
  func hexEncodedString() -> String {
    let hexDigits = Array("0123456789abcdef".utf16)
    var hexChars = [UTF16.CodeUnit]()
    hexChars.reserveCapacity(count * 2)

    for byte in self {
      let (index1, index2) = Int(byte).quotientAndRemainder(dividingBy: 16)
      hexChars.append(hexDigits[index1])
      hexChars.append(hexDigits[index2])
    }

    return String(utf16CodeUnits: hexChars, count: hexChars.count)
  }
}
Swift 4-从十六进制字符串到数据 我还添加了一个快速解决方案,用于将十六进制字符串转换为数据(基于a)

扩展字符串{
///此字符串中十六进制字节的数据表示形式。
func hexDecodedData()->数据{
//获取此字符串的UTF8字符
设字符=数组(utf8)
//将字节保留在UInt8数组中,并使用l