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

Der*_*ang 482 go

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

因为不是所有的strings都是100个字符长,所以剩下的部分byte array0s 填充.

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

在C string将在终止0,所以我不知道什么的巧妙的最佳方式转移byte arraystring在Golang.

Dan*_*iel 487

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

s := string(byteArray[:n])
Run Code Online (Sandbox Code Playgroud)

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

n := bytes.Index(byteArray, []byte{0})
Run Code Online (Sandbox Code Playgroud)

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

n := bytes.IndexByte(byteArray, 0)
Run Code Online (Sandbox Code Playgroud)

  • 实际上string(byteArray)也会这样做,并将保存切片创建 (55认同)
  • 您应该使用[`bytes.IndexByte()`](https://golang.org/pkg/bytes/#IndexByte)搜索单个`byte`而不是[`bytes.Index()`](https: //golang.org/pkg/bytes/#Index),包含1个字节的字节片. (6认同)
  • 但是要清楚,这是将一个字节序列转换为_hopefully_一个有效的UTF-8字符串(而不是说,Latin-1等,或者一些格式错误的UTF-8序列).施法时Go不会为你检查. (3认同)
  • 我知道我迟到了一年,但是我应该提到*大多数*方法返回读取的字节数。例如,binary.Read()可以读入[32]字节,但您不知道是否已填满全部32个字节。 (2认同)
  • @CameronKerr 来自 [blog.golang.org/strings](https://blog.golang.org/strings):“重要的是要预先声明字符串可以保存任意字节。不需要保存 Unicode 文本, UTF-8 文本,或任何其他预定义格式。就字符串的内容而言,它完全等同于字节切片。” (2认同)

mat*_*tes 369

关于什么?

s := string(byteArray[:])
Run Code Online (Sandbox Code Playgroud)

  • 问题具体说`string(byteArray [:])`包含`^ @`字符 (23认同)
  • 与`string(byteArray)`的区别是什么?为什么需要使用`[:]`复制数组? (22认同)
  • @RobertZaremba>一个字符串实际上是一个只读的字节片.你不能将字节数组直接转换为字符串,所以先切片然后再串. (6认同)
  • 请阅读问题。它明确指出这不会在第一个 null 处终止字符串(就像 C 中的 strcpy 一样)。非常烦人的是,这个错误的答案得到了如此高的投票。IMO 的最佳答案是上面提到的,使用 IndexByte()。 (4认同)
  • 最干净的方法来转换字节数组肯定.我想知道strings.Trim是否有助于删除空字节?http://golang.org/pkg/strings/#example_Trim (3认同)
  • 这应该是正确的答案.太棒了!! (3认同)
  • @RobertZaremba对于字节切片,你不需要添加`[:]`,对于字节数组,你可以. (3认同)
  • 这是不正确的,因为结果字符串 `s` 的长度为 100 并且包含许多尾随 0 字节(未打印)。请参阅 https://play.golang.org/p/y4AF-DFqp42 (2认同)

小智 62

简单的解决方案:

str := fmt.Sprintf("%s", byteArray)
Run Code Online (Sandbox Code Playgroud)

我不确定这是多么高效.

  • 不幸的是,这并没有删除尾随零。`str` 的长度为 100。请参阅 https://play.golang.org/p/XWrmqCbIwkB (2认同)

pet*_*rSO 14

例如,

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)
}
Run Code Online (Sandbox Code Playgroud)

输出:

C:  100 [97 98 99 0]
Go: 3 abc
Run Code Online (Sandbox Code Playgroud)


Pau*_*kin 6

下面的代码正在寻找'\ 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))
}
Run Code Online (Sandbox Code Playgroud)

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

  • 您的代码无法编译,即使它已经编译,它也无法正常工作.二进制搜索算法在排序数组中查找指定值的位置.数组不一定是排序的. (8认同)
  • 我不理解downvotes.代码编译并且是正确的,假设字符串除了结尾之外不包含\ 0.代码正在寻找\ 0,并且在问题的假设下,数组可以被认为是"排序的",因为所有非\ 0都在\ 0之前,并且所有代码都在检查.如果downvoters可以找到代码不起作用的示例输入,那么我将删除答案. (6认同)
  • 如果所有空字节都在字符串的末尾,则进行二进制搜索。 (2认同)
  • 如果输入为 `[]byte{0}`,则会给出错误的结果。在这种情况下,`FirstZero()` 应该返回 `0`,因此当切片结果将是 `""` 时,而是返回 `1` 并且切片结果在 `"\x00"`。 (2认同)