Saya perlu membaca [100]byte
untuk mentransfer banyakstring
data.
Karena tidak semua string
karakter memiliki panjang 100 karakter, bagian sisanya byte array
diisi dengan0
s.
Jika saya mengonversi [100]byte
ke string
oleh string(byteArray[:])
:, tailing 0
akan ditampilkan sebagai^@^@
s.
Di C string
akan berakhir 0
, jadi saya bertanya-tanya apa cara terbaik untuk mengubahnya byte array
ke string
Golang.
^@
itu tidak muncul, tetapi pasti sudah ada di sana jika Anda mengujinya di terminal atau yang serupa. Alasan untuk ini, adalah bahwa Go tidak berhenti mengubah array byte ke string ketika menemukan 0.len(string(bytes))
dalam contoh Anda adalah 5 dan tidak 1. Itu tergantung pada fungsi output, apakah string sepenuhnya (dengan nol) dicetak atau tidak.string(body)
.Jawaban:
Metode yang membaca data menjadi irisan byte mengembalikan jumlah byte yang dibaca. Anda harus menyimpan nomor itu dan kemudian menggunakannya untuk membuat string Anda. Jika
n
jumlah byte dibaca, kode Anda akan terlihat seperti ini:Untuk mengonversi string penuh ini dapat digunakan:
Ini setara dengan:
Jika karena alasan tertentu Anda tidak tahu
n
, Anda bisa menggunakanbytes
paket untuk menemukannya, dengan asumsi input Anda tidak memiliki karakter nol yang tertanam di dalamnya.Atau seperti yang ditunjukkan icza, Anda dapat menggunakan kode di bawah ini:
sumber
bytes.IndexByte()
pencarian mana untuk satubyte
alih-alihbytes.Index()
dengan irisan byte yang berisi 1 byte.Bagaimana dengan?
sumber
string(byteArray[:])
berisi^@
karakterstring(byteArray)
? Mengapa Anda perlu menyalin array menggunakan[:]
?[:]
, untuk byte array, Anda harus melakukannya.Solusi sederhana:
Saya tidak yakin bagaimana performant ini.
sumber
Sebagai contoh,
Keluaran:
sumber
Kode berikut mencari '\ 0', dan di bawah asumsi pertanyaan array dapat dianggap diurutkan karena semua bukan - '\ 0' mendahului semua '\ 0'. Asumsi ini tidak akan berlaku jika array dapat berisi '\ 0' dalam data.
Temukan lokasi nol-byte pertama menggunakan pencarian biner, kemudian iris.
Anda dapat menemukan nol-byte seperti ini:
Mungkin lebih cepat hanya dengan memindai secara naif array byte mencari nol-byte, terutama jika sebagian besar string Anda pendek.
sumber
[]byte{0}
. Dalam hal iniFirstZero()
harus kembali0
jadi ketika mengiris hasil akan""
, tetapi sebaliknya mengembalikan1
dan mengiris hasil"\x00"
.Saat Anda tidak tahu panjang pasti byte non-nil dalam array, Anda bisa memotongnya terlebih dahulu:
sumber
bytes.Trim
mengambil irisan, bukan array (Anda akan perluarr[:]
jika arr sebenarnya a[100]byte
sebagai negara pertanyaan). b)bytes.Trim
adalah fungsi yang salah untuk digunakan di sini. Untuk input seperti[]byte{0,0,'a','b','c',0,'d',0}
itu akan mengembalikan "abc \ x00d" bukannya "" c) sudah ada jawaban yang benar yang menggunakanbytes.IndexByte
, cara terbaik untuk menemukan byte nol pertama.Kenapa tidak ini?
sumber
byteArray[:]
karenabytes.NewBuffer
mengambil[]byte
; b) pertanyaannya mengatakan array memiliki angka nol yang tidak Anda setujui; c) jika sebaliknya variabel Anda adalah[]byte
(satu-satunya cara baris Anda akan dikompilasi) maka baris Anda hanyalah cara lambat untuk melakukannyastring(v)
.Hanya digunakan untuk penyempurnaan kinerja.
sumber
string
mungkin memiliki implikasi serius jika nanti byte byte diubah.string
nilai-nilai di Go didefinisikan tidak dapat diubah, yang menjadi dasar dibangunnya seluruh runtime dan pustaka Go. Anda akan memindahkan diri Anda ke tengah-tengah bug yang paling misterius dan kesalahan runtime jika Anda menyusuri jalan ini.Gunakan irisan alih-alih array untuk membaca. mis.
io.Reader
menerima irisan, bukan array.Gunakan mengiris bukannya nol padding.
Contoh:
sumber
s := a[:n]
ataus := string(a[:n])
jika Anda membutuhkan string. Jikan
tidak tersedia secara langsung, harus dihitung, misalnya dengan mencari byte spesifik / nol dalam buffer (array) seperti yang disarankan Daniel.Saya mencoba beberapa metode beberapa kali saya panik:
Tapi ini akhirnya berhasil.
string(Data[:])
sumber
Meskipun tidak terlalu berkinerja, satu-satunya solusi yang dapat dibaca adalah
Contoh lengkap untuk memiliki array byte gaya-C:
Contoh lengkap untuk memiliki string gaya go tidak termasuk nulls:
Ini mengalokasikan sepotong byte. Jadi perhatikan kinerja jika digunakan banyak atau berulang kali.
sumber
Berikut adalah kode untuk mengompresi byte array ke string
sumber
Inilah cara tercepat:
sumber
fmt
lebih cepat dilakukanfmt.Printf("%s", bytes)
daripada menggunakanstring(bytes)
).Saya ketika dengan solusi rekursif.
sumber
fmt.Println(CToGoString([]byte("ctogo\x00\x00"), "") == "ctogo")
harus dicetaktrue
, dicetakfalse
.[100]byte
tetapi[]byte
, dan tidak menghapus'\x00'
byte. Kecepatannya (tergantung pada input) lebih lambat oleh beberapa urutan besarnya dibandingkan dengan kecepatan jawaban yang diterima.