Как преобразовать нулевой байтовый массив в строку?

Мне нужно прочитать [100]byte чтобы передать кучу string данных.

Поскольку не все string имеют длину точно 100 символов, оставшаяся часть byte array дополняется 0 с.

Если я передам [100]byte в string помощью: string(byteArray[:]), хвостовой 0 будет отображаться как ^@^@ s.

В C string будет заканчиваться на 0, поэтому мне интересно, каков наилучший способ аккуратно передать byte array в string в Golang.

Ответ 1

методы, считывающие данные в байтовые фрагменты, возвращают количество прочитанных байтов. Вы должны сохранить это число, а затем использовать его для создания своей строки. n - количество прочитанных байтов, ваш код будет выглядеть так:

s := string(byteArray[:n])

Если по какой-то причине у вас нет n, вы можете использовать пакет байтов, чтобы найти его, если ваш вход не имеет нулевого символа.

n := bytes.Index(byteArray, []byte{0})

Или, как указал icza, вы можете использовать следующий код:

n := bytes.IndexByte(byteArray, 0)

Ответ 2

Как насчет?

s := string(byteArray[:])

Ответ 3

Упрощенное решение:

str := fmt.Sprintf("%s", byteArray)

Я не уверен, насколько это возможно.

Ответ 4

Например,

package main

import "fmt"

func CToGoString(c []byte) string {
    n := -1
    for i, b := range c {
        if b == 0 {
            break
        }
        n = i
    }
    return string(c[:n+1])
}

func main() {
    c := [100]byte{'a', 'b', 'c'}
    fmt.Println("C: ", len(c), c[:4])
    g := CToGoString(c[:])
    fmt.Println("Go:", len(g), g)
}

Вывод:

C:  100 [97 98 99 0]
Go: 3 abc

Ответ 5

Следующий код ищет '\ 0', и в предположениях вопроса массив можно считать отсортированным, поскольку все non- '\ 0' предшествуют всем '\ 0'. Это предположение не будет выполнено, если массив может содержать '\ 0' в данных.

Найдите местоположение первого нулевого байта, используя двоичный поиск, а затем срез.

Вы можете найти нуль-байта следующим образом:

package main

import "fmt"

func FirstZero(b []byte) int {
    min, max := 0, len(b)
    for {
        if min + 1 == max { return max }
        mid := (min + max) / 2
        if b[mid] == '\000' {
            max = mid
        } else {
            min = mid
        }
    }
    return len(b)
}
func main() {
    b := []byte{1, 2, 3, 0, 0, 0}
    fmt.Println(FirstZero(b))
}

Возможно, быстрее просто наивно сканировать массив байтов, ищущий нулевой байт, особенно если большинство ваших строк коротки.

Ответ 6

Когда вы не знаете точную длину не-nil байтов в массиве, вы можете обрезать ее сначала:

string (bytes.Trim(arr, "\ x00"))

Ответ 7

Используйте только для настройки производительности.

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

func BytesToString(b []byte) string {
    return *(*string)(unsafe.Pointer(&b))
}

func StringToBytes(s string) []byte {
    return *(*[]byte)(unsafe.Pointer(&s))
}

func main() {
    b := []byte{'b', 'y', 't', 'e'}
    s := BytesToString(b)
    fmt.Println(s)
    b = StringToBytes(s)
    fmt.Println(string(b))
}

Ответ 8

Почему не это?

bytes.NewBuffer(byteArray).String()

Ответ 9

  • Для чтения используйте срезы вместо массивов. например, io.Reader принимает срез, а не массив.

  • Используйте срез вместо нулевого заполнения.

Пример:

buf := make([]byte, 100)
n, err := myReader.Read(buf)
if n == 0 && err != nil {
        log.Fatal(err)
}

consume(buf[:n]) // consume will see exact (not padded) slice of read data

Ответ 10

Я несколько раз пробовал несколько методов, и у меня была паника:

ошибка времени выполнения: пределы среза вне диапазона.

Но это, наконец, сработало.

string(Data[:])

Ответ 11

Вот более быстрый способ:

resp, _ := http.Get("https://www.something.com/something.xml")
bytes, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
fmt.Println(string(bytes)) //just convert with string() function

Ответ 12

I, когда с рекурсивным решением.

func CToGoString(c []byte, acc string) string {

    if len(c) == 0 {
        return acc
    } else {
        head := c[0]
        tail := c[1:]
        return CToGoString(tail, acc + fmt.Sprintf("%c", head))
    }
}

func main() {
    b := []byte{some char bytes}
    fmt.Println(CToGoString(b, ""))
}