如何将字节缓冲区中以null结尾的字符串转换为Go中的字符串?

时间:2021-11-05 20:40:50

This:

这个:

label := string([]byte{97, 98, 99, 0, 0, 0, 0})
fmt.Printf("%s\n", label)

does this (^@ is the null-byte):

这样做(^ @是空字节):

go run test.go 
abc^@^@^@

4 个解决方案

#1


6  

use the strings package.

使用字符串包。

package main

import (
    "fmt"
    "strings"
)

func main() {
    label := string([]byte{97, 98, 99, 0, 0, 0, 0})
    fmt.Println(strings.TrimSpace(label))
}

#2


10  

Note that the first answer will only work with strings that have only a run of zeroes after the null terminator; however, a proper C-style null-terminated string ends at the first \0 even if it's followed by garbage. For example, []byte{97,98,99,0,99,99,0} should be parsed as abc, not abc^@cc.

请注意,第一个答案仅适用于在null终止符后仅运行零的字符串;但是,正确的C风格的以null结尾的字符串在第一个\ 0结束,即使它后面跟着垃圾。例如,[] byte {97,98,99,0,99,99,0}应解析为abc,而不是abc ^ @ cc。

To properly parse this, use string.Index, as follows, to find the first \0 and use it to slice the original byte-slice:

要正确解析它,请使用string.Index,如下所示,找到第一个\ 0并使用它来切片原始字节切片:

package main

import (
    "fmt"
    "strings"
)

func main() {
    label := []byte{97,98,99,0,99,99,0}
    s := label[:strings.Index(string(label), "\x00")]
    fmt.Println(string(s))
}

EDIT: Was printing the shortened version as a []byte instead of as a string. Thanks to @serbaut for the catch.

编辑:将缩短版本打印为[]字节而不是字符串。感谢@serbaut的捕获。

#3


6  

There's this function hidden inside Go's syscall package that finds the first null byte ([]byte{0}) and returns the length. I'm assuming it's called clen for C-Length.

在Go的syscall包中隐藏了这个函数,它找到第一个空字节([] byte {0})并返回长度。我假设它被称为C-Length的clen。

Sorry I'm a year late on this answer, but I think it's a lot simpler than the other two (no unnecessary imports, etc.)

对不起,我对这个答案迟了一年,但我认为这比其他两个要简单得多(没有不必要的进口等)

func clen(n []byte) int {
    for i := 0; i < len(n); i++ {
        if n[i] == 0 {
            return i
        }
    }
    return len(n)
}

So,

所以,

label := []byte{97, 98, 99, 0, 0, 0, 0}
s := label[:clen(label)]
fmt.Println(string(s))

What that ^ says is to set s to the slice of bytes in label from the beginning to the index of clen(label).

^所说的是将s设置为从开头到clen(label)索引的标签中的字节切片。

The result would be abc with a length of 3.

结果将是abc,长度为3。

#4


0  

The first answer will not work!!

第一个答案是行不通的!!

func TrimSpace(s []byte) []byte {
    return TrimFunc(s, unicode.IsSpace)
}

func IsSpace(r rune) bool {
    // This property isn't the same as Z; special-case it.
    if uint32(r) <= MaxLatin1 {
        switch r {
        case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0:
            return true
        }
        return false
    }
    return isExcludingLatin(White_Space, r)
}

there is not "\x00" in func IsSpace at all.

func IsSpace中根本没有“\ x00”。

#1


6  

use the strings package.

使用字符串包。

package main

import (
    "fmt"
    "strings"
)

func main() {
    label := string([]byte{97, 98, 99, 0, 0, 0, 0})
    fmt.Println(strings.TrimSpace(label))
}

#2


10  

Note that the first answer will only work with strings that have only a run of zeroes after the null terminator; however, a proper C-style null-terminated string ends at the first \0 even if it's followed by garbage. For example, []byte{97,98,99,0,99,99,0} should be parsed as abc, not abc^@cc.

请注意,第一个答案仅适用于在null终止符后仅运行零的字符串;但是,正确的C风格的以null结尾的字符串在第一个\ 0结束,即使它后面跟着垃圾。例如,[] byte {97,98,99,0,99,99,0}应解析为abc,而不是abc ^ @ cc。

To properly parse this, use string.Index, as follows, to find the first \0 and use it to slice the original byte-slice:

要正确解析它,请使用string.Index,如下所示,找到第一个\ 0并使用它来切片原始字节切片:

package main

import (
    "fmt"
    "strings"
)

func main() {
    label := []byte{97,98,99,0,99,99,0}
    s := label[:strings.Index(string(label), "\x00")]
    fmt.Println(string(s))
}

EDIT: Was printing the shortened version as a []byte instead of as a string. Thanks to @serbaut for the catch.

编辑:将缩短版本打印为[]字节而不是字符串。感谢@serbaut的捕获。

#3


6  

There's this function hidden inside Go's syscall package that finds the first null byte ([]byte{0}) and returns the length. I'm assuming it's called clen for C-Length.

在Go的syscall包中隐藏了这个函数,它找到第一个空字节([] byte {0})并返回长度。我假设它被称为C-Length的clen。

Sorry I'm a year late on this answer, but I think it's a lot simpler than the other two (no unnecessary imports, etc.)

对不起,我对这个答案迟了一年,但我认为这比其他两个要简单得多(没有不必要的进口等)

func clen(n []byte) int {
    for i := 0; i < len(n); i++ {
        if n[i] == 0 {
            return i
        }
    }
    return len(n)
}

So,

所以,

label := []byte{97, 98, 99, 0, 0, 0, 0}
s := label[:clen(label)]
fmt.Println(string(s))

What that ^ says is to set s to the slice of bytes in label from the beginning to the index of clen(label).

^所说的是将s设置为从开头到clen(label)索引的标签中的字节切片。

The result would be abc with a length of 3.

结果将是abc,长度为3。

#4


0  

The first answer will not work!!

第一个答案是行不通的!!

func TrimSpace(s []byte) []byte {
    return TrimFunc(s, unicode.IsSpace)
}

func IsSpace(r rune) bool {
    // This property isn't the same as Z; special-case it.
    if uint32(r) <= MaxLatin1 {
        switch r {
        case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xA0:
            return true
        }
        return false
    }
    return isExcludingLatin(White_Space, r)
}

there is not "\x00" in func IsSpace at all.

func IsSpace中根本没有“\ x00”。