J'ai besoin de lire [100]byte
pour transférer un tas de données string
.
Étant donné que tous les string
s ne comportent pas exactement 100 caractères, la partie restante du byte array
est complétée par 0
s.
Si je transfère [100]byte
à string
avec: string(byteArray[:])
, les résidus 0
s 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.
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)
Qu'en est-il de?
s := string(byteArray[:])
Solution simpliste:
str := fmt.Sprintf("%s", byteArray)
Je ne sais pas si c'est performant.
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
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.
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"))
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))
}
Pourquoi pas ça?
bytes.NewBuffer(byteArray).String()
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[:])
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
_