如何在切片上查找而从切片复制到阵列

时间:2018-11-22 10:56:32

标签: arrays go struct slice reader

我正在编写一个用于处理二进制格式的库。

我有一个带有数组变量的结构,出于文档目的,我想保留它。

我还需要从输入的字节片中寻找并分辨出来。

一些伪代码:

type foo struct {
    boo [5]byte
    coo [3]byte
}

func main() {

    // input is a []byte full of datas, read from a file

    var bar foo

    // Here i need something that writes 5 bytes to bar.foo from input
    bar.foo = somefunc(input, numberOfFoo) // ???
    // I need also tell() and seek()
    input.seek(n)

}

我该如何使用一个功能呢?

1 个答案:

答案 0 :(得分:3)

在字节片输入上操作

您可以使用内置的copy()将字节从源切片复制到目标中。如果您有一个数组,请对其进行切片以获得切片,例如bar.boo[:]。为了寻找,只需在源切片中使用不同的偏移量,也可以通过对其进行切片,例如input[startPos:]

例如:

input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}

var bar foo
copy(bar.boo[:], input)

// Skip 2 bytes, seek to the 8th byte:
input = input[7:]

copy(bar.coo[:], input)

fmt.Printf("%+v", bar)

输出(在Go Playground上尝试):

{boo:[1 2 3 4 5] coo:[8 9 10]}

创建一个ReadSeeker

另一种选择是将输入字节片包装到io.ReadSeeker之类的bytes.Reader中,然后您可以从中读取内容。

例如:

input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}
r := bytes.NewReader(input)

var bar foo
if _, err := io.ReadFull(r, bar.boo[:]); err != nil {
    panic(err)
}

// Skip 2 bytes, seek to the 8th byte:
if _, err := r.Seek(7, io.SeekStart); err != nil {
    panic(err)
}

if _, err := io.ReadFull(r, bar.coo[:]); err != nil {
    panic(err)
}

fmt.Printf("%+v", bar)

输出相同,请在Go Playground上尝试。

使用encoding/binary

另一种解决方案是使用encoding/binary一步读取整个结构。

为此,我们需要导出字段,并且必须插入一个覆盖跳过字节的匿名或空白字段:

type foo struct {
    Boo [5]byte
    _   [2]byte // don't care
    Coo [3]byte
}

具有上述类型,我们可以像这样一步来阅读所有内容:

input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}
r := bytes.NewReader(input)

var bar foo
if err := binary.Read(r, binary.LittleEndian, &bar); err != nil {
    panic(err)
}

fmt.Printf("%+v", bar)

输出类似,除了它还会显示匿名字段(在Go Playground上尝试):

{Boo:[1 2 3 4 5] _:[0 0] Coo:[8 9 10]}

查看相关答案:Why use arrays instead of slices?

直接从原始文件读取

您提到您的input分片来自读取文件。请注意,您不需要先读取文件,因为os.File实现了io.Reader,甚至实现了io.ReadSeeker,这意味着您可以直接从中读取文件,请参见创建{{ 1}} 部分。您也可以直接应用ReadSeeker解决方案,因为我们也在该解决方案中使用了阅读器。