J'ai besoin de lire [100]byte
pour transférer un tas de string
données.
Étant donné que tous les string
s ne comportent pas exactement 100 caractères, la partie restante du byte array
est remplie de 0
s.
Si je convertis [100]byte
en string
par string(byteArray[:])
:, les 0
s sont affichés comme ^@^@
s.
En C la string
prendra fin à 0
, alors je me demande quelle est la meilleure façon de convertir ce byte array
à string
en golang.
^@
ne s'affiche pas, mais il aurait été là si vous l'aviez testé dans le terminal ou quelque chose de similaire. La raison en est que Go n'arrête pas de convertir le tableau d'octets en chaîne lorsqu'il trouve un 0.len(string(bytes))
dans votre exemple est 5 et non 1. Cela dépend de la fonction de sortie, si la chaîne est entièrement (avec des zéros) imprimée ou pas.string(body)
.Réponses:
Les méthodes qui lisent des données dans des tranches d'octets renvoient le nombre d'octets lus. Vous devez enregistrer ce nombre, puis l'utiliser pour créer votre chaîne. Si
n
est le nombre d'octets lus, votre code ressemblera à ceci:Pour convertir la chaîne complète, cela peut être utilisé:
Cela équivaut à:
Si pour une raison que vous ne connaissez pas
n
, vous pouvez utiliser lebytes
package pour le trouver, en supposant que votre entrée ne comporte pas de caractère nul.Ou comme l'a souligné icza, vous pouvez utiliser le code ci-dessous:
la source
bytes.IndexByte()
qui recherche un seulbyte
au lieu d'bytes.Index()
une tranche d'octets contenant 1 octet.Qu'en est-il de?
la source
string(byteArray[:])
contient des^@
personnagesstring(byteArray)
? Pourquoi devez-vous copier le tableau à l'aide de[:]
?[:]
, pour les tableaux d'octets, vous le faites.Solution simpliste:
Je ne sais pas à quel point c'est performant.
la source
Par exemple,
Production:
la source
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.
Recherchez 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:
Il peut être plus rapide de balayer naïvement le tableau d'octets à la recherche du zéro octet, surtout si la plupart de vos chaînes sont courtes.
la source
[]byte{0}
. Dans ce cas, ilFirstZero()
devrait revenir0
quand le résultat de la coupe serait""
, mais à la place, il reviendrait1
et la coupe résulterait en"\x00"
.Lorsque vous ne connaissez pas la longueur exacte des octets non nuls dans le tableau, vous pouvez d'abord le couper:
la source
bytes.Trim
prend une tranche, pas un tableau (vous auriez besoinarr[:]
si arr est en fait un[100]byte
comme l'indique la question). b)bytes.Trim
est la mauvaise fonction à utiliser ici. Pour une entrée telle[]byte{0,0,'a','b','c',0,'d',0}
qu'elle renverra "abc \ x00d" au lieu de "" c), il existe déjà une réponse correcte qui utilisebytes.IndexByte
, la meilleure façon de trouver le premier octet zéro.Pourquoi pas ça?
la source
byteArray[:]
depuisbytes.NewBuffer
prend un[]byte
; b) la question disait que le tableau a des zéros de fin que vous ne traitez pas; c) si à la place votre variable est un[]byte
(la seule façon dont votre ligne se compilera), alors votre ligne est juste une manière lente de le fairestring(v)
.À utiliser uniquement pour l'optimisation des performances.
la source
string
peut avoir de sérieuses implications si plus tard la tranche d'octets est modifiée.string
les valeurs de Go sont définies comme immuables, sur lesquelles l'intégralité du runtime Go et des bibliothèques s'appuient. Vous vous téléporterez au milieu des bugs les plus mystérieux et des erreurs d'exécution si vous suivez cette voie.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 nul.
Exemple:
la source
s := a[:n]
ous := string(a[:n])
si vous avez besoin d'une chaîne. S'iln
n'est pas directement disponible, il doit être calculé, par exemple en recherchant un octet spécifique / zéro dans le tampon (tableau) comme le suggère Daniel.J'ai essayé quelques méthodes quelques fois, j'ai eu la panique:
Mais cela a finalement fonctionné.
string(Data[:])
la source
Bien que peu performante, la seule solution lisible est
Exemple complet pour avoir un tableau d'octets de style C:
Exemple complet pour avoir une chaîne de style go excluant les null:
Cela alloue une tranche de tranche d'octets. Gardez donc un œil sur les performances en cas d'utilisation intensive ou répétée.
la source
Voici le code pour compresser le tableau d'octets en chaîne
la source
Voici le moyen le plus rapide:
la source
fmt
c'est plus rapide à fairefmt.Printf("%s", bytes)
qu'à utiliserstring(bytes)
).Je quand avec une solution récursive.
la source
fmt.Println(CToGoString([]byte("ctogo\x00\x00"), "") == "ctogo")
doit imprimertrue
, il imprimefalse
.[100]byte
mais un[]byte
et ne supprime pas les'\x00'
octets. Sa vitesse (dépend de l'entrée) est plus lente de plusieurs ordres de grandeur par rapport à la vitesse de la réponse acceptée.