代码之家  ›  专栏  ›  技术社区  ›  Amanda

Swift-将UInt8字节转换为位数组

  •  7
  • Amanda  · 技术社区  · 8 年前

    我试图解码protobuff编码的消息,所以我需要将protobuff消息中的第一个字节(键)转换为位,这样我就可以找到字段号。如何将UInt8(字节)转换为位数组?

    伪代码

    private func findFieldNum(from byte: UInt8) -> Int {
        //Byte is 0001 1010
        var fieldNumBits = byte[1] ++ byte[2] ++ byte[3] ++ byte[4] //concatentates bits to get 0011
        getFieldNum(from: fieldNumBits) //Converts 0011 to field number, 2^1 + 2^0 = 3
    }
    

    this question

    5 回复  |  直到 8 年前
        1
  •  18
  •   mohak    8 年前

    下面是一个基本函数,用于获取 Bit

    func bits(fromByte byte: UInt8) -> [Bit] {
        var byte = byte
        var bits = [Bit](repeating: .zero, count: 8)
        for i in 0..<8 {
            let currentBit = byte & 0x01
            if currentBit != 0 {
                bits[i] = .one
            }
    
            byte >>= 1
        }
    
        return bits
    }
    

    在这里 一点

    enum Bit: UInt8, CustomStringConvertible {
        case zero, one
    
        var description: String {
            switch self {
            case .one:
                return "1"
            case .zero:
                return "0"
            }
        }
    }
    

    let byte: UInt8 = 0x1f
    
    print(bits(fromByte: byte))
    

    将是:

    [1, 1, 1, 1, 1, 0, 0, 0]
    
        2
  •  3
  •   jdelaune    6 年前

    改进 mohak 的答案。具有泛型函数或扩展,以满足不仅仅是 UInt8

    enum Bit: UInt8, CustomStringConvertible {
        case zero, one
    
        var description: String {
            switch self {
            case .one:
                return "1"
            case .zero:
                return "0"
            }
        }
    }
    
    func bits<T: FixedWidthInteger>(fromBytes bytes: T) -> [Bit] {
        // Make variable
        var bytes = bytes
        // Fill an array of bits with zeros to the fixed width integer length
        var bits = [Bit](repeating: .zero, count: T.bitWidth)
        // Run through each bit (LSB first)
        for i in 0..<T.bitWidth {
            let currentBit = bytes & 0x01
            if currentBit != 0 {
                bits[i] = .one
            }
    
            bytes >>= 1
        }
    
        return bits
    }
    
    extension FixedWidthInteger {
        var bits: [Bit] {
            // Make variable
            var bytes = self
            // Fill an array of bits with zeros to the fixed width integer length
            var bits = [Bit](repeating: .zero, count: self.bitWidth)
            // Run through each bit (LSB first)
            for i in 0..<self.bitWidth {
                let currentBit = bytes & 0x01
                if currentBit != 0 {
                    bits[i] = .one
                }
    
                bytes >>= 1
            }
    
            return bits
        }
    }
    
        3
  •  0
  •   paulvs    8 年前

    // An example byte
    let a: UInt8 = 0b00011010
    
    // Extract the bits (using 0b01111000 as a bitmask) 
    // in indices 1 to 4, then shift right by 3 places
    // to remove indices 5 to 7
    var b = (a & 0b01111000) >> 3 
    
    // In this case, b is now 3 (or 11 in binary)
    print(b)
    
        4
  •  0
  •   kanobius    5 年前

    较短的一个:

    enum Bit { case zero, one }
    
    func bit(_ i: Int, of uint8: UInt8) -> Bit {
      let first8PowersOf2 = (0...7).map { return UInt8(1) << $0 }
      return (uint8 & first8PowersOf2[i] != 0) ? Bit.one : Bit.zero
    }
    
    func bitsFrom(_ uint8: UInt8) -> [Bit] {
      return Array((0...7)).reversed().map { bit($0, of: uint8) }
    }
    

    我们可以将其用作:

    let fromUInt8  = bitsFrom(42)
    let fromBinary = bitsFrom(0b01011010)
    let fromHexa   = bitsFrom(0xFF)
    
        5
  •  0
  •   Krzysztof Majewski    3 年前

    func bits(fromByte byte: UInt8) -> [Bool] {
    var byte = byte
    var bits = [Bool](repeating: false, count: 8)
    for i in 0..<8 {
       let currentBit = byte & 0x01
       if currentBit != 0 {
          bits[i] = true
       }
       byte >>= 1
     }
     return bits
    

    }