web-dev-qa-db-fra.com

Comment convertir un tableau d'octets à zéro terminal en chaîne?

J'ai besoin de lire [100]byte pour transférer un tas de données string.

Étant donné que tous les strings ne comportent pas exactement 100 caractères, la partie restante du byte array est complétée par 0s.

Si je transfère [100]byte à string avec: string(byteArray[:]), les résidus 0s sont affichés sous la forme ^@^@s.

En C, la string prendra fin le 0, alors je me demande quel est le meilleur moyen de transférer intelligemment un byte array à string à Golang.

468
Derrick Zhang

les méthodes qui lisent les données dans des tranches d'octets renvoient le nombre d'octets lus. Vous devriez enregistrer ce nombre, puis l'utiliser pour créer votre chaîne. n étant le nombre d'octets lus, votre code devrait ressembler à ceci:

s := string(byteArray[:n])

Si, pour une raison quelconque, vous n'avez pas n, vous pouvez utiliser le paquet d'octets pour le trouver, en supposant que votre entrée ne comporte pas de caractère nul.

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

Ou, comme l'a souligné icza, vous pouvez utiliser le code ci-dessous:

n := bytes.IndexByte(byteArray, 0)
478
Daniel

Qu'en est-il de?

s := string(byteArray[:])
368
mattes

Solution simpliste:

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

Je ne sais pas si c'est performant.

61
marcusljx

Par exemple,

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

Sortie:

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

Le code suivant recherche '\ 0', et sous les hypothèses de la question, le tableau peut être considéré comme trié puisque tous les non -\0 'précèdent tous les'\0 '. Cette hypothèse ne tient pas si le tableau peut contenir '\ 0' dans les données.

Recherchez l'emplacement du premier zéro octet à l'aide d'une recherche binaire, puis découpez.

Vous pouvez trouver le zéro octet comme ceci:

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

Il peut être plus rapide d'analyser naïvement le tableau d'octets à la recherche du zéro octet, surtout si la plupart de vos chaînes sont courtes.

6
Paul Hankin

Lorsque vous ne connaissez pas la longueur exacte d'octets non nil dans le tableau, vous pouvez le rogner en premier:

chaîne (octets.Trim (arr, "\ x00"))

3
zach

Utiliser uniquement pour le réglage des performances.

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

Pourquoi pas ça?

bytes.NewBuffer(byteArray).String()
1
Bhagya Prasad NR

J'ai essayé quelques méthodes à plusieurs reprises, j'ai paniqué:

erreur d'exécution: les limites de la tranche sont hors limites.

Mais cela a finalement fonctionné.

string(Data[:])

0
Gaurav Singh
  • Utilisez des tranches au lieu de tableaux pour la lecture. par exemple. io.Reader accepte une tranche, pas un tableau.

  • Utilisez le découpage au lieu du remplissage zéro.

Exemple:

_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
_
0
zzzz