Ich muss lesen [100]byte
, um eine Reihe von string
Daten zu übertragen.
Da nicht alle string
s genau 100 Zeichen lang sind, wird der verbleibende Teil von s byte array
mit 0
s aufgefüllt .
Wenn ich [100]byte
nach string
by konvertiere string(byteArray[:])
, werden die Tailing 0
s als ^@^@
s angezeigt .
In C die string
enden auf 0
, so frage ich mich , was der beste Weg, dies zu konvertieren , byte array
um string
in Golang.
^@
nicht angezeigt , aber es wäre da gewesen, wenn du es im Terminal oder ähnlichem getestet hättest. Der Grund dafür ist, dass Go die Konvertierung des Byte-Arrays in eine Zeichenfolge nicht beendet, wenn eine 0len(string(bytes))
in Ihrem Beispiel 5 und nicht 1 gefunden wird. Es hängt von der Ausgabefunktion ab, ob die Zeichenfolge vollständig (mit Nullen) gedruckt ist oder nicht.string(body)
.Antworten:
Methoden, die Daten in Byte-Slices lesen, geben die Anzahl der gelesenen Bytes zurück. Sie sollten diese Nummer speichern und dann zum Erstellen Ihrer Zeichenfolge verwenden. Wenn
n
die Anzahl der gelesenen Bytes angegeben ist, sieht Ihr Code folgendermaßen aus:Um die vollständige Zeichenfolge zu konvertieren, kann Folgendes verwendet werden:
Dies entspricht:
Wenn Sie es aus irgendeinem Grund nicht wissen
n
, können Sie dasbytes
Paket verwenden, um es zu finden, vorausgesetzt, in Ihre Eingabe ist kein Nullzeichen eingebettet.Oder wie icza betonte, können Sie den folgenden Code verwenden:
quelle
bytes.IndexByte()
, um nach einem einzelnen zu suchen,byte
anstattbytes.Index()
mit einem Byte-Slice, das 1 Byte enthält.Wie wäre es mit?
quelle
string(byteArray[:])
enthält^@
string(byteArray)
? Warum müssen Sie das Array mit kopieren[:]
?[:]
, für Byte-Arrays tun Sie dies.Einfache Lösung:
Ich bin mir nicht sicher, wie performant das ist.
quelle
Zum Beispiel,
Ausgabe:
quelle
Der folgende Code sucht nach '\ 0', und unter den Annahmen der Frage kann das Array als sortiert betrachtet werden, da alle Nicht-'\ 0' vor allen '\ 0' stehen. Diese Annahme gilt nicht, wenn das Array '\ 0' in den Daten enthalten kann.
Suchen Sie die Position des ersten Null-Bytes mithilfe einer binären Suche und schneiden Sie dann.
Sie finden das Null-Byte folgendermaßen:
Es kann schneller sein, das Byte-Array naiv nach dem Null-Byte zu durchsuchen, insbesondere wenn die meisten Ihrer Zeichenfolgen kurz sind.
quelle
[]byte{0}
. In diesem FallFirstZero()
sollte dies so zurückkehren0
, wenn das Slicing-Ergebnis wäre""
, aber stattdessen kehrt es zurück1
und das Slicing führt zu"\x00"
.Wenn Sie die genaue Länge der Nicht-Null-Bytes im Array nicht kennen, können Sie sie zuerst zuschneiden:
quelle
bytes.Trim
nimmt ein Slice, kein Array (Sie würden es brauchen,arr[:]
wenn arr tatsächlich ein ist,[100]byte
wie in der Frage angegeben). b)bytes.Trim
ist hier die falsche Funktion. Für Eingaben[]byte{0,0,'a','b','c',0,'d',0}
, die "abc \ x00d" anstelle von "" c) zurückgeben, gibt es bereits eine korrekte Antwort, diebytes.IndexByte
den besten Weg zum Finden des ersten Null-Bytes verwendet.Warum nicht das?
quelle
byteArray[:]
da esbytes.NewBuffer
ein benötigt[]byte
; b) Die Frage besagt, dass das Array nachgestellte Nullen hat, mit denen Sie sich nicht befassen. c) Wenn Ihre Variable stattdessen a ist[]byte
(die einzige Möglichkeit, wie Ihre Zeile kompiliert wird), ist Ihre Zeile nur eine langsame Methodestring(v)
.Nur zur Leistungsoptimierung verwenden.
quelle
string
kann schwerwiegende Folgen haben, wenn das Byte-Slice später geändert wird.string
Werte in Go werden als unveränderlich definiert, auf denen die gesamte Go-Laufzeit und die Bibliotheken aufbauen. Sie werden sich in die Mitte der mysteriösesten Fehler und Laufzeitfehler teleportieren, wenn Sie diesen Weg gehen.Verwenden Sie zum Lesen Slices anstelle von Arrays. zB
io.Reader
akzeptiert ein Slice, kein Array.Verwenden Sie das Schneiden anstelle der Nullpolsterung.
Beispiel:
quelle
s := a[:n]
oders := string(a[:n])
wenn Sie eine Zeichenfolge benötigen. Wennn
es nicht direkt verfügbar ist, muss es berechnet werden, z. B. indem nach einem bestimmten / Null-Byte im Puffer (Array) gesucht wird, wie Daniel vorschlägt.Ich habe einige Male einige Methoden ausprobiert, als ich in Panik geriet:
Aber das hat endlich funktioniert.
string(Data[:])
quelle
Obwohl nicht extrem performant, ist die einzige lesbare Lösung
Vollständiges Beispiel für ein Byte-Array im C-Stil:
Vollständiges Beispiel für eine Go-Zeichenfolge ohne Nullen:
Dadurch wird ein Stück Byte zugewiesen. Behalten Sie also die Leistung im Auge, wenn sie stark oder wiederholt verwendet wird.
quelle
Hier ist der Code zum Komprimieren des Byte-Arrays in einen String
quelle
Hier ist der schnellere Weg:
quelle
fmt
ist dies schnellerfmt.Printf("%s", bytes)
als die Verwendungstring(bytes)
).Ich wenn mit einer rekursiven Lösung.
quelle
fmt.Println(CToGoString([]byte("ctogo\x00\x00"), "") == "ctogo")
sollte gedruckt werdentrue
, er wird gedrucktfalse
.[100]byte
sondern a[]byte
und entfernt keine'\x00'
Bytes. Seine Geschwindigkeit (abhängig von der Eingabe) ist um mehrere Größenordnungen langsamer als die Geschwindigkeit der akzeptierten Antwort.