如何将零终止的字节数组转换为字符串?

本文翻译自: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转换为stringstring(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, ""))
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值