首页 文章

将字节数组转换为字符串的最佳方法是什么?

提问于
浏览
409

我需要阅读 [100]byte 以传输一堆 string 数据 .

因为并非所有的 string 都是100个字符长,所以 byte array 的剩余部分用 0 填充 .

如果我通过 string(byteArray[:])[100]byte 转换为 string ,则拖尾 0 显示为 ^@^@ s .

在C中 string 将在 0 终止,所以我想知道在Golang中将 byte array 巧妙地转移到 string 的最佳方法是什么 .

12 回答

  • 0

    将数据读入字节片的方法返回读取的字节数 . 您应该保存该号码,然后使用它来创建您的字符串 . n 是读取的字节数,您的代码如下所示:

    s := string(byteArray[:n])
    

    如果由于某种原因你没有 n ,你可以使用bytes包来找到它,假设你的输入中没有空字符 .

    n := bytes.Index(byteArray, []byte{0})
    

    或者正如icza指出的那样,您可以使用以下代码:

    n := bytes.IndexByte(byteArray, 0)
    
  • 419

    关于什么?

    s := string(byteArray[:])
    
  • 6

    简单的解决方案:

    str := fmt.Sprintf("%s", byteArray)
    

    我不确定这是多么高效 .

  • 2

    例如,

    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
    
  • 334

    下面的代码正在寻找'\ 0',并且在问题的假设下,数组可以被认为是排序的,因为所有非'\ 0'都在'0'之前 . 如果数组在数据中包含'\ 0',则此假设将不成立 .

    使用二进制搜索找到第一个零字节的位置,然后切片 .

    你可以找到这样的零字节:

    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))
    }
    

    只是天真地扫描字节数组寻找零字节可能更快,特别是如果你的大多数字符串很短 .

  • 13

    Olny用于性能调优 .

    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))
    }
    
  • -8

    如果您不知道数组中非零字节的确切长度,可以先修剪它:

    string(bytes.Trim(arr,“\ x00”))

  • 47

    我几次尝试了几种方法,我感到恐慌:

    运行时错误:切片范围超出范围 .

    但这最终奏效了 .

    string(Data[:])

  • 1

    为什么不呢?

    bytes.NewBuffer(byteArray).String()
    
  • -1
    • 使用切片而不是数组进行读取 . 例如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
    
  • 2

    这是更快的方法:

    resp, _ := http.Get("https://www.something.com/something.xml")
    bytes, _ := ioutil.ReadAll(resp.Body)
    resp.Body.Close()
    fmt.Println(string(bytes)) //just convert with string() function
    
  • 4

    我在使用递归解决方案时 .

    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, ""))
    }
    

相关问题