将字节数组转换为string的最佳方法是什么?
我需要读取[100]byte
来传输一串string
数据。
由于不是所有的string
都精确到100,所以byte array
的其余部分用0
填充。
如果我将[100]byte
为string
: string(byteArray[:])
,则string(byteArray[:])
0
将显示为^@^@
s。
在C中string
将终止于0
,所以我不知道什么是巧妙地传输byte array
到string
的最佳方式。
将数据读入字节片段的方法返回读取的字节数。 您应该保存该号码,然后用它来创build您的string。 n
是读取的字节数,你的代码看起来像这样:
s := string(byteArray[:n])
如果由于某种原因,你没有n
,你可以使用字节包来find它,假设你的input中没有空字符。
n := bytes.Index(byteArray, []byte{0})
或者正如icza指出的,你可以使用下面的代码:
n := bytes.IndexByte(byteArray, 0)
关于什么?
s := string(byteArray[:])
简单的解决scheme:
str := fmt.Sprintf("%s", byteArray)
我不确定这是如何高性能的。
例如,
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) }
输出:
C: 100 [97 98 99 0] Go: 3 abc
下面的代码正在寻找'\ 0',在这个问题的假设下,数组可以被认为是sorting的,因为所有非'\ 0'都在'\ 0'之前。 如果数组中可以包含“\ 0”,这个假设就不会成立。
使用二进制search查找第一个零字节的位置,然后切片。
你可以find像这样的零字节:
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)) }
只是天真地扫描字节数组寻找零字节可能会更快,特别是如果大部分string都很短。
package main import ( "fmt" "reflect" "unsafe" ) func BytesToString(b []byte) string { bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) sh := reflect.StringHeader{bh.Data, bh.Len} return *(*string)(unsafe.Pointer(&sh)) } func StringToBytes(s string) []byte { sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) bh := reflect.SliceHeader{sh.Data, sh.Len, 0} return *(*[]byte)(unsafe.Pointer(&bh)) } func main() { b := []byte{'b', 'y', 't', 'e'} s := BytesToString(b) fmt.Println(s) b = StringToBytes(s) fmt.Println(string(b)) }
-
使用切片而不是arrays进行阅读。 例如
io.Reader
接受一个切片,而不是一个数组。 -
使用切片而不是零填充。
例:
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
为什么不呢?
bytes.NewBuffer(byteArray).String()
我什么时候用recursion解决scheme。
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, "")) }