将位串转换为字节数组

时间:2018-02-06 15:33:23

标签: arrays go

我似乎无法将1s和0s的字符串转换为字节数组。

这是我到目前为止的代码:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    /* goal: convert a bit string (ex "10110110") to a byte array */
    bitString := "00000000000000000000000100111000100001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011"

    myBytes := make([]byte, 16)
    for len(bitString) > 7 {
        currentByteStr := bitString[:8]
        bitString = bitString[8:]
        currentByteInt, _ := strconv.ParseUint(currentByteStr, 2, 8)
        currentByte := byte(currentByteInt)
        myBytes = append(myBytes, currentByte)
    }

    fmt.Println(myBytes)

}

我显然遗漏了一些东西,但我似乎无法将该大小的字符串转换为字节数组。

编辑我收到了第一个错误:

[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 56 134 0 0 0 0 0 0 0 0 0 0 3]

但它没有输出我期望的字节数组的样子:

{{1}}

我原以为它是十六进制?那不是golang中字节数组的样子吗?

3 个答案:

答案 0 :(得分:2)

我会选择创建一个新类型butString,其中包含转换为[]字节和[]字符串的方法(如果您愿意,可以使用hex)。这也应该防止输入字符串不能被8整除。

package main

import (
    "encoding/hex"
    "fmt"
    "strconv"
)

type bitString string

func (b bitString) AsByteSlice() []byte {
    var out []byte
    var str string

    for i := len(b); i > 0; i -= 8 {
        if i-8 < 0 {
            str = string(b[0:i])
        } else {
            str = string(b[i-8 : i])
        }
        v, err := strconv.ParseUint(str, 2, 8)
        if err != nil {
            panic(err)
        }
        out = append([]byte{byte(v)}, out...)
    }
    return out
}

func (b bitString) AsHexSlice() []string {
    var out []string
    byteSlice := b.AsByteSlice()
    for _, b := range byteSlice {
        out = append(out, "0x" + hex.EncodeToString([]byte{b}))
    }
    return out
}

func main() {
    x := bitString("00000000000000000000000100111000100001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011")
    fmt.Println(x.AsByteSlice())
    fmt.Println(x.AsHexSlice())
}

<强>输出

[64 0 1 56 134 0 0 0 0 0 0 0 0 0 0 3]
[0x00 0x00 0x01 0x38 0x86 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x03]

Playgroud

如果速度是一个问题,那么可以通过分配具有适当容量的切片并自己跟踪索引来实现优化。

答案 1 :(得分:1)

我认为在这个非常明确的任务的情况下,最好只用手构建数组。

func main() {
    /* goal: convert a bit string (ex "10110110") to a byte array */
    bitString := "00000000000000000000000100111000100001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011"

    lenB := len(bitString) / 8 + 1
    bs:=make([]byte,lenB)

    count,i := 0,0
    var now byte
    for _,v:=range bitString {
        if count == 8 {
            bs[i]=now
            i++
            now,count = 0,0
        }
        now = now << 1 + byte(v-'0')
        count++
    }
    if count!=0 {
        bs[i]=now << (8-byte(count))
        i++
    }

    bs=bs[:i:i]
    fmt.Println(bs)

}

代码使用count来计算自上次&#34; flush&#34;以来消耗的数字位数。和&#34;冲洗&#34;当有8.变量i保留字节区域的信息时,循环后可能会有最终的刷新。

byte(v-'0')是从符文转换为一点。

游乐场:https://play.golang.org/p/eB1mc_FjiQc

答案 2 :(得分:0)

这是一个简单的解决方案。

package main

import (
    "errors"
    "fmt"
)

var ErrRange = errors.New("value out of range")

func bitStringToBytes(s string) ([]byte, error) {
    b := make([]byte, (len(s)+(8-1))/8)
    for i := 0; i < len(s); i++ {
        c := s[i]
        if c < '0' || c > '1' {
            return nil, ErrRange
        }
        b[i>>3] |= (c - '0') << uint(7-i&7)
    }
    return b, nil
}

func main() {
    s := "00000000000000000000000100111000100001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011"
    b, err := bitStringToBytes(s)
    if err != nil {
        fmt.Println(s, err)
    }
    fmt.Println(b)
    fmt.Printf("%b\n", b)
    fmt.Printf("%x\n", b)
}

游乐场:https://play.golang.org/p/Ils1gzkY4Dg

输出:

[0 0 1 56 134 0 0 0 0 0 0 0 0 0 0 3]
[0 0 1 111000 10000110 0 0 0 0 0 0 0 0 0 0 11]
00000138860000000000000000000003

注意:已更新@leaf bebop的优化。