本文翻译自:How to convert a zero-terminated byte array to string?
I need to read [100]byte
to transfer a bunch of string
data. 我需要读取[100]byte
来传输一串string
数据。
Because not all of the string
s are precisely 100 characters long, the remaining part of the byte array
is padded with 0
s. 因为并非所有string
s的长度都恰好是100个字符,所以byte array
的其余部分将填充0
s。
If I convert [100]byte
to string
by: string(byteArray[:])
, the tailing 0
s are displayed as ^@^@
s. 如果通过以下方式将[100]byte
转换为string
: string(byteArray[:])
,则string(byteArray[:])
0
s将显示为^@^@
s。
In C the string
will terminate upon 0
, so I wonder what's the best way to convert this byte array
to string
in Golang. 在C中, string
将以0
结尾,因此我想知道在Golang中将此byte array
转换为string
的最佳方法是什么。
#1楼
参考:https://stackoom.com/question/xhuT/如何将零终止的字节数组转换为字符串
#2楼
methods that read data into byte slices return the number of bytes read. 将数据读取到字节片中的方法返回读取的字节数。 You should save that number and then use it to create your string. 您应该保存该数字,然后使用它来创建您的字符串。 n
being the number of bytes read, your code would look like this: n
是读取的字节数,您的代码如下所示:
s := string(byteArray[:n])
If for some reason you don't have n
, you could use the bytes package to find it, assuming your input doesn't have a null character in it. 如果由于某种原因您没有n
,则可以使用bytes包找到它,假设您的输入中没有空字符。
n := bytes.Index(byteArray, []byte{0})
Or as icza pointed out, you can use the code below: 或如icza所指出的,您可以使用以下代码:
n := bytes.IndexByte(byteArray, 0)
#3楼
Use slices instead of arrays for reading. 使用切片而不是数组进行读取。 eg
io.Reader
accepts a slice, not an array. 例如io.Reader
接受一个分片,而不是一个数组。Use slicing instead of zero padding. 使用切片而不是零填充。
Example: 例:
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
#4楼
For example, 例如,
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)
}
Output: 输出:
C: 100 [97 98 99 0]
Go: 3 abc
#5楼
The following code is looking for '\\0', and under the assumptions of the question the array can be considered sorted since all non-'\\0' precede all '\\0'. 下面的代码正在寻找'\\ 0',并且在问题的假设下,可以将数组视为已排序,因为所有非'\\ 0'都在所有'\\ 0'之前。 This assumption won't hold if the array can contain '\\0' within the data. 如果数组的数据中可以包含“ \\ 0”,则该假设将不成立。
Find the location of the first zero-byte using a binary search, then slice. 使用二进制搜索找到第一个零字节的位置,然后切片。
You can find the zero-byte like this: 您可以找到如下所示的零字节:
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))
}
It may be faster just to naively scan the byte array looking for the zero-byte, especially if most of your strings are short. 仅天真地扫描字节数组以查找零字节可能会更快,尤其是在大多数字符串较短的情况下。
#6楼
I when with a recursive solution. 我什么时候有递归的解决方案。
func CToGoString(c []byte, acc string) string {
if len(c) == 0 {
return acc
} else {
head := c[0]
tail := c[1:]
return CToGoString(tail, acc + fmt.Sprintf("%c", head))
}
}
func main() {
b := []byte{some char bytes}
fmt.Println(CToGoString(b, ""))
}