Quelle est la meilleure façon de convertir un tableau d'octets en chaîne?

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

Parce que tout le string n'est pas précisément long de 100, la partie restante du byte array est rembourrée avec 0 S.

Si je tansfer [100]byte à string par: string(byteArray[:]), la filature 0s sont affichés sous la forme ^@^@s.

En C, le {[1] } se terminera sur 0, donc je me demande Quel est le meilleur moyen de transférer intelligemment byte array à string.

390
demandé sur Bijan 2013-01-09 11:19:48

11 réponses

Les méthodes qui lisent des données en tranches d'octets renvoient le nombre d'octets lus. Vous devez enregistrer le nombre et l'utiliser pour créer votre chaîne. n étant le nombre d'octets lus, votre code ressemblerait à ceci:

s := string(byteArray[:n])

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

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

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

n := bytes.IndexByte(byteArray, 0)
402
répondu Daniel 2015-08-07 07:25:51

De quoi?

s := string(byteArray[:])
323
répondu mattes 2015-06-12 13:02:40

Solution Simpliste:

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

Je ne sais pas à quel point c'est performant.

41
répondu marcusljx 2016-11-02 08:57:14

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
répondu peterSO 2013-01-09 15:30:00

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 tiendra pas si le tableau peut contenir '\ 0 ' dans les données.

Trouvez l'emplacement du premier octet zéro à 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 de scanner naïvement le tableau d'octets à la recherche du zéro octet, surtout si la plupart de vos les cordes sont courtes.

6
répondu Paul Hankin 2016-06-26 14:23:13
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))
}
3
répondu yuen 2014-12-23 05:46:40

J'ai essayé quelques méthodes quelques fois j'ai eu la panique:

Erreur D'exécution: découper les limites hors de portée.

Mais cela a finalement fonctionné.

string(Data[:])

2
répondu Gaurav Singh 2018-05-03 14:50:51

Pourquoi pas ça?

bytes.NewBuffer(byteArray).String()
1
répondu Bhagya Prasad NR 2015-06-26 18:24:13

Lorsque vous ne connaissez pas la longueur exacte des octets non nuls dans le tableau, vous pouvez le couper en premier:

Chaîne (octets.Garniture(arr, "\x00"))

1
répondu zach 2018-03-21 07:02:23
  • Utilisez des tranches au lieu de tableaux pour la lecture. par exemple io.Reader accepte une tranche, pas un tableau.

  • Utilisez le tranchage au lieu de zéro remplissage.

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
répondu zzzz 2016-08-03 11:29:50

I quand avec une solution récursive.

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, ""))
}
-8
répondu Romel Campbell 2013-06-06 02:03:20