0

I can't seem to convert a bit string of 1s and 0s to a byte array.

Here is the code I have so far:

package main

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

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

    bitNum, err := strconv.ParseUint(bitString, 2, 128) // turn my 128-bit bitstring into an int

    if err != nil {
        panic(err) // currently panics with "value out of range"
    }

    // convert my integer to a byte array
    // code from https://stackoverflow.com/questions/16888357/convert-an-integer-to-a-byte-array
    bs := make([]byte, 128)                   // allocate memory for my byte array
    binary.LittleEndian.PutUint64(bs, bitNum) // convert my bitnum to a byte array
    fmt.Println(bs)

}

I am clearly missing something, but I can't seem to convert a bit string of that size to a byte array.

edit I got passed the first error with this:

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)

}

but it doesn't output what I would expect a byte array to look like:

[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]

I would have expected it to be hex? is that not what a byte array looks like in golang?

7
  • You will probably need to use big integers: golang.org/pkg/math/big Commented Feb 6, 2018 at 15:36
  • cosume the string 8bits by 8 bits to form a byte (uint8). Commented Feb 6, 2018 at 15:38
  • I just clicked that link. I'll look at the sizes of those. And yes, I should do it byte by byte i suppose. Commented Feb 6, 2018 at 15:38
  • Do you want each sequence of 8 bits to be stored as a byte, the whole number as something that can be used as a number, or one byte for each bit? Your sample code sounds like one big number, requiring math/big Commented Feb 6, 2018 at 15:51
  • Sorry @Marc, that was unclear. I am wanting an array of bytes. Commented Feb 6, 2018 at 15:54

2 Answers 2

3

I think in case of this very specified tasks, it is good to construct the array just by hands.

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)

}

The code uses a count to count the numbers of digit consumed since last "flush" and "flush" when there is 8. variable i keeps info on the bytes area and after the loop there might be a final flush.

byte(v-'0') is the converting from rune to a bit.

Playground: https://play.golang.org/p/eB1mc_FjiQc

Sign up to request clarification or add additional context in comments.

2 Comments

Your answer got me the same (except I just wanted my byte array to be a bit larger).
@Jeff waht do you mean by larger?
2

I would opt for making a new type, bitString, with methods for converting to a []byte and []string (for hex if you like). This should also guard against an input string not evenly divisible by 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())
}

OUTPUT

[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

If speed is a concern, then optimization can be achieved by allocating the slice with the appropriate capacity and tracking the index yourself.

3 Comments

The most overhead is in strconv.ParseUint. Not memory allocation.
@leafbebop fair enough... but that's what pprof is for :).
And that is auctually what pprof told me before (I can't find the exact code but basically the same).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.