从4,3中创建8位二进制数据,并在Golang中创建1位数据

问题描述 投票:1回答:1

需要使用版本(4位),计数(3位),标识符(1位)形成标题(8位)数据。如何在Golang中实现?例如:

version: 1 (0001)
count: 3 (011)
identifier: 1(1)

Header: 00010111 (23)

我正在执行以下操作,但是代码繁琐。我如何有效地做到这一点?


const (
    VersionSize       binary.Bits  = 4
    countSize         binary.Bits  = 3
    IdentifierSize    binary.Bits  = 1
)

type header struct {
    version      uint8 
    count        uint8
    identifier   uint8
}

func main() {
    headerObj := &header{version:1, count:3, identifier:1}
    headerBytes := encode(headerObj)
    // prints [23]
    fmt.PrintLn(headerBytes)
}

func (h *header) encode() []byte {
    var header []byte

    vercountIdBinary := toBinary(h.version, versionSize) + toBinary(h.count,countSize) + toBinary(h.identifier, IdentifierSize)

    vercountIdByte, _ := strconv.ParseInt(vercountIdBinary, 2, 8)
    header = append(header, byte(vercountIdByte))

    return header
}

func toBinary(value interface{}, bitSize binary.Bits) string {
    format := "%0" + strconv.Itoa(int(bitSize)) + "b"
    return fmt.Sprintf(format, value)
}
go binary bitwise-operators
1个回答
0
投票

将位打包和解包可以简单地通过位屏蔽和移位实现。

例如,将位打包成一个数字,掩码并分配第一个,然后将结果与位号或下一个数据左移(为其留出足够的空间)。然后屏蔽第二个数字,并使用按位或将其“相加”。然后再次移动第三个数字的大小,然后重复。

解压:用最后一个字段的大小遮盖结果,然后得到最后一个数字。向右移动已解码编号的大小的数据,并以下一个(相反的顺序)编号的大小屏蔽,就得到了编号。重复此过程,直到您解码了所有数字。

例如,将identifier打包到最高有效位,将count打包到中间有效位,但version打包到最低有效位,但是可以通过相反的顺序打包字段来执行相反的顺序:

const (
    BitsVersion = 4
    BitsCount   = 3
    BitsId      = 1
)

const (
    MaskVersion = 1<<BitsVersion - 1
    MaskCount   = 1<<BitsCount - 1
    MaskId      = 1<<BitsId - 1
)

type header struct {
    version    uint8
    count      uint8
    identifier uint8
}

func (h *header) ToByte() uint8 {
    var b uint8

    b = h.identifier & MaskId
    b <<= BitsCount
    b |= h.count & MaskCount
    b <<= BitsVersion
    b |= h.version & MaskVersion

    return b
}

func (h *header) ParseByte(b uint8) {
    h.version = b & MaskVersion
    b >>= BitsVersion
    h.count = b & MaskCount
    b >>= BitsCount
    h.identifier = b & MaskId
}

正在测试:

h := &header{
    version:    3,
    count:      2,
    identifier: 1,
}
fmt.Printf("%+v\n", h)

b := h.ToByte()

h2 := &header{}
h2.ParseByte(b)
fmt.Printf("%+v\n", h2)

将输出(在Go Playground上尝试):

&{version:3 count:2 identifier:1}
&{version:3 count:2 identifier:1}

[请注意,如果您需要针对io.Writer流,对多个数据进行此操作,则可以使用github.com/icza/bitio库(公开:我是作者)。

© www.soinside.com 2019 - 2024. All rights reserved.