Как преобразовать нулевой байтовый массив в строку?
Мне нужно прочитать [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, ""))
}