strings golang functions convert bytes array string go byte

string - golang - ¿Cuál es la mejor manera de convertir la matriz de bytes a la cadena?



string functions golang (12)

Necesito leer el [100]byte para transferir un montón de datos de string .

Como no todas las string tienen exactamente 100 caracteres, la parte restante de la byte array se rellena con 0 s.

Si transfiero el [100]byte a la string por: string(byteArray[:]) , las colas 0 s se muestran como ^@^@ s.

En C, la string terminará en 0 , así que me pregunto cuál es la mejor manera de transferir inteligentemente una byte array a la string en Golang.


¿Por qué no esto?

bytes.NewBuffer(byteArray).String()


¿Qué pasa?

s := string(byteArray[:])


Aquí está la manera más rápida:

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


Cuando no conoce la longitud exacta de bytes no nulos en la matriz, puede recortarla primero:

cadena (bytes.Trim (arr, "/ x00"))


El siguiente código busca ''/ 0'', y bajo los supuestos de la pregunta, la matriz se puede considerar ordenada ya que todos los que no son ''/ 0'' preceden a todos ''/ 0''. Esta suposición no se mantendrá si la matriz puede contener ''/ 0'' dentro de los datos.

Busque la ubicación del primer byte cero utilizando una búsqueda binaria, luego divídala.

Puedes encontrar el byte cero así:

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)) }

Puede ser más rápido escanear ingenuamente la matriz de bytes buscando el byte cero, especialmente si la mayoría de las cadenas son cortas.


Olny usa para afinar el rendimiento.

package main import ( "fmt" "reflect" "unsafe" ) func BytesToString(b []byte) string { bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) sh := reflect.StringHeader{bh.Data, bh.Len} return *(*string)(unsafe.Pointer(&sh)) } func StringToBytes(s string) []byte { sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) bh := reflect.SliceHeader{sh.Data, sh.Len, 0} return *(*[]byte)(unsafe.Pointer(&bh)) } func main() { b := []byte{''b'', ''y'', ''t'', ''e''} s := BytesToString(b) fmt.Println(s) b = StringToBytes(s) fmt.Println(string(b)) }


Por ejemplo,

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) }

Salida:

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


Probé algunos métodos pocas veces me dio pánico:

Error de tiempo de ejecución: rebanar límites fuera de rango.

Pero esto finalmente funcionó.

string(Data[:])


Solución simplista:

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

Sin embargo, no estoy seguro de cómo es esto.


Yo cuando con una solución recursiva.

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, "")) }


los métodos que leen datos en segmentos de bytes devuelven el número de bytes leídos. Debes guardar ese número y luego usarlo para crear tu cadena. Siendo el número de bytes leídos, su código se vería así:

s := string(byteArray[:n])

Si por alguna razón no tiene n , puede usar el paquete de bytes para encontrarlo, asumiendo que su entrada no tiene un carácter nulo.

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

O como icza señaló, puede utilizar el siguiente código:

n := bytes.IndexByte(byteArray, 0)


  • Use rodajas en lugar de matrices para leer. por ejemplo, io.Reader acepta un sector, no una matriz.

  • Utilice rebanar en lugar de cero relleno.

Ejemplo:

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