Muszę przeczytać, [100]byte
aby przenieść sporo string
danych.
Ponieważ nie wszystkie string
litery mają dokładnie 100 znaków, pozostała część byte array
jest wypełniona literą 0
s.
Jeśli przekonwertować [100]byte
do string
przez: string(byteArray[:])
, odpadzie 0
s są wyświetlane jako ^@^@
s.
W C string
wygasa po 0
, więc zastanawiam się, jaki jest najlepszy sposób przekonwertować to byte array
do string
w Golang.
^@
nie pokazuje się, ale byłoby tam, gdybyś przetestował to w terminalu lub coś podobnego. Powodem tego jest to, że Go nie przestaje konwertować tablicy bajtów na ciąg, gdy znajdzie 0.len(string(bytes))
w twoim przykładzie jest 5, a nie 1. To zależy od funkcji wyjściowej, czy ciąg zostanie wydrukowany w całości (z zerami) albo nie.string(body)
.Odpowiedzi:
Metody, które odczytują dane do plasterków bajtów, zwracają liczbę odczytanych bajtów. Powinieneś zapisać tę liczbę, a następnie użyć jej do utworzenia łańcucha Jeśli
n
jest to liczba odczytanych bajtów, kod wyglądałby następująco:Aby przekonwertować pełny ciąg, można tego użyć:
Jest to równoważne z:
Jeśli z jakiegoś powodu nie wiesz
n
, możesz użyćbytes
pakietu, aby go znaleźć, zakładając, że twój wpis nie zawiera znaku null.Lub, jak wskazał icza, możesz użyć kodu poniżej:
źródło
bytes.IndexByte()
który wyszukuje pojedynczybyte
zamiastbytes.Index()
z bajtem zawierającym 1 bajt.Co powiesz na?
źródło
string(byteArray[:])
zawiera^@
znakistring(byteArray)
? Dlaczego musisz skopiować tablicę za pomocą[:]
?[:]
, w przypadku tablic bajtów wystarczy .Uproszczone rozwiązanie:
Nie jestem jednak pewien, jak wydajne to jest.
źródło
Na przykład,
Wynik:
źródło
Poniższy kod szuka „\ 0” i przy założeniu pytania tablicę można uznać za posortowaną, ponieważ wszystkie inne niż „\ 0” poprzedzają wszystkie „\ 0”. To założenie nie będzie miało zastosowania, jeśli tablica może zawierać „\ 0” w danych.
Znajdź lokalizację pierwszego zera za pomocą wyszukiwania binarnego, a następnie pokrój.
Możesz znaleźć bajt zerowy w ten sposób:
Szybsze może być tylko naiwne skanowanie tablicy bajtów w poszukiwaniu bajtu zerowego, szczególnie jeśli większość ciągów znaków jest krótka.
źródło
[]byte{0}
. W takim przypadkuFirstZero()
powinien zwrócić,0
więc kiedy wynik krojenia będzie""
, ale zamiast tego zwraca1
i krojenie wyników"\x00"
.Jeśli nie znasz dokładnej długości bajtów innych niż zero w tablicy, możesz ją najpierw przyciąć:
źródło
bytes.Trim
pobiera plasterek, a nie tablicę (będziesz potrzebować,arr[:]
jeśli arr jest w rzeczywistości,[100]byte
jak podaje pytanie). b)bytes.Trim
jest niewłaściwą funkcją do użycia tutaj. Dla danych wejściowych takich jak[]byte{0,0,'a','b','c',0,'d',0}
zwróci „abc \ x00d” zamiast „” c) istnieje już poprawna odpowiedź, która używabytes.IndexByte
, najlepszy sposób na znalezienie pierwszego bajtu zerowego.Dlaczego nie to
źródło
byteArray[:]
ponieważbytes.NewBuffer
trwa[]byte
; b) pytanie mówi, że tablica ma końcowe zera, z którymi nie masz do czynienia; c) jeśli zamiast tego twoja zmienna jest[]byte
(jedynym sposobem, w jaki twoja linia się skompiluje), to twoja linia jest tylko powolnym sposobemstring(v)
.Używaj tylko do strojenia wydajności.
źródło
string
może mieć poważne konsekwencje, jeśli później zostanie zmodyfikowany wycinek bajtu.string
wartości w Go są zdefiniowane jako niezmienne, na których bazują całe środowisko wykonawcze Go i biblioteki. Jeśli pójdziesz tą ścieżką, przeniesiesz się w sam środek najbardziej tajemniczych błędów i błędów w czasie wykonywania.Do czytania używaj wycinków zamiast tablic. np.
io.Reader
akceptuje plasterek, a nie tablicę.Zastosuj krojenie zamiast zerowania.
Przykład:
źródło
s := a[:n]
lubs := string(a[:n])
jeśli potrzebujesz łańcucha. Jeślin
nie jest bezpośrednio dostępny, należy go obliczyć, np. Szukając określonego / zerowego bajtu w buforze (tablicy), jak sugeruje Daniel.Kilka razy próbowałem kilka metod, wpadłem w panikę:
Ale to w końcu zadziałało.
string(Data[:])
źródło
Chociaż nie jest to wyjątkowo wydajne, jedynym możliwym do odczytania rozwiązaniem jest
Pełny przykład posiadania tablicy bajtów w stylu C:
Pełny przykład posiadania łańcucha stylu go z wyłączeniem wartości null:
To przydziela plasterek bajtu. Miej oko na wydajność, jeśli jest intensywnie lub wielokrotnie używana.
źródło
Oto kod do kompresji tablicy bajtów na ciąg
źródło
Oto szybszy sposób:
źródło
fmt
jest to szybszefmt.Printf("%s", bytes)
niż użyciestring(bytes)
).Ja z rozwiązaniem rekurencyjnym.
źródło
fmt.Println(CToGoString([]byte("ctogo\x00\x00"), "") == "ctogo")
powinien zostać wydrukowanytrue
, zostanie wydrukowanyfalse
.[100]byte
ale[]byte
nie usuwa'\x00'
bajtów. Jego prędkość (w zależności od danych wejściowych) jest mniejsza o wiele rzędów wielkości w porównaniu do prędkości przyjętej odpowiedzi.