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

本文翻译自: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, ""))
}
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

第1章 声明和初始化 基本类型 1.1 我该如何决定使用哪种整数类型? 1.2 什么不精确定义标准类型的大小? 1.3 因C语言没有精确定义类型的大小,所以我一般都用typedef定义int16和int32。然后根据实际的机器环境把它们定义int、short、long等类型。这样看来,所有的问题都解决了,是吗? 1.4 新的64位机上的64位类型是什么样的? 指针声明 1.5 这样的声明有什么问题?char*p1,p2;我在使用p2的时候报错了。 1.6 我想声明一个指针,并它分配一些空间,但却不行。这样的代码有什么问题?char*p;*p=malloc(10); 声明风格 1.7 怎样声明和定义全局变量和函数最好? 1.8 如何在C中实现不透明(抽象)数据类型? 1.9 如何生成“半全局变量”,就是那种只能被部分源文件中的部分函数访问的变量? 存储类型 1.10 同一个静态(static)函数或变量的所有声明都必需包含static存储类型吗? 1.11 extern在函数声明中是什么意思? 1.12 关键字auto到底有什么用途? 类型定义(typedef) 1.13 对于用户定义类型,typedef和#define有什么区别? 1.14 我似乎不能成功定义一个链表。我试过typedefstruct{char*item;NODEPTRnext;}*NODEPTR;但是编译器报了错误信息。难道在C语言中结构不能包含指向自己的指针吗? 1.15 如何定义一对相互引用的结构? 1.16 Struct{ }x1;和typedefstruct{ }x2;这两个声明有什么区别? 1.17 “typedefint(*funcptr)();”是什么意思? const限定词 1.18 我有这样一组声明:typedefchar*charp;constcharpp;什么是p而不是它指向的字符const? 1.19 什么不能像下面这样在初始式和数组维度值中使用const值?constintn=5;inta[n]; 1.20 constchar*p、charconst*p和char*constp有什么区别? 复杂的声明 1.21 怎样建立和理解非常复杂的声明?例如定义一个包含N个指向返回指向字符的指针的函数的指针的数组? 1.22 如何声明返回指向同类型函数的指针的函数?我在设计一个状态机,用函数表示每种状态,每个函数都会返回一个指向下一个状态的函数的指针。可我找不到任何方法来声明这样的函数——感觉我需要一个返回指针的函数,返回的指针指向的又是返回指针的函数……,如此往复,以至无穷。 数组大小 1.23 能否声明和传入数组大小一致的局部数组,或者由其他参数指定大小的参数数组? 1.24 我在一个文件中定义了一个extern数组,然后在另一个文件中使用,什么sizeof取不到数组的大小? 声明问题 1.25 函数只定义了一次,调用了一次,但编译器提示非法重声明了。 *1.26 main的正确定义是什么?voidmain正确吗? 1.27 我的编译器总在报函数原型不匹配的错误,可我觉得没什么问题。这是什么? 1.28 文件中的第一个声明就报出奇怪的语法错误,可我看没什么问题。这是什么? 1.29 什么我的编译器不允许我定义大数组,如doublearray[256][256]? 命名空间 1.30如何判断哪些标识符可以使用,哪些被保留了? 初始化 1.31 对于没有显式初始化的变量的初始值可以作怎样的假定?如果一个全局变量初始值”,它可否作空指针或浮点? 1.32 下面的代码什么不能编译?intf(){chara[]="Hello,world!";} *1.33 下面的初始化有什么问题?编译器提示“invalidinitializers”或其他信息。char*p=malloc(10); 1.34 chara[]="stringliteral";和char*p="stringliteral";初始化有什么区别?当我向p[i]赋值的时候,我的程序崩溃了。 1.35 chara{[3]}="abc";是否合法? 1.36 我总算弄清楚函数指针的声明方法了,但怎样才能初始化呢? 1.37 能够初始化联合吗? 第2章 结构、联合和枚举 结构声明 2.1 structx1{ };和typedefstruct{ }x2;有什么不同? 2.2 这样的代码什么不对?structx{ };xthestruct; 2.3 结构可以包含指向自己的指针吗? 2.4 在C语言中用什么方法实现抽象数据类型最好? *2.5 在C语言中是否有模拟继承等面向对象程序设计特性的好方法? 2.6 什么声明externf(structx*p);给我报了一个晦涩
©️2021 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值