如何在切片上查找而从切片复制到阵列 [英] How to copy from slice to array with seeking onto slice

查看:63
本文介绍了如何在切片上查找而从切片复制到阵列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing a library to deal with a binary format.

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

I have a struct with array vars, that I would like to keep for documentation purposes.

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

I need also to seek and tell from the input slice of bytes.

一些伪代码:

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)

}

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

How can I do that with a single function?

推荐答案

对字节片输入进行操作

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

Operating on byte slice input

You may use the builtin copy() to copy bytes from a source slice into a destination. If you have an array, slice it to obtain a slice, e.g. bar.boo[:]. To seek, just use a different offset in the source slice, also by reslicing it, e.g. 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)

输出(在游乐场上尝试):

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

创建 ReadSeeker

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

Creating a ReadSeeker

Another option is to wrap your input byte slice into an io.ReadSeeker such as bytes.Reader, then you can read from it.

例如:

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)

输出相同,请在游乐场上进行尝试.

Output is the same, try it on the Go Playground.

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

Yet another solution would be to use encoding/binary to read your whole struct in one step.

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

In order to do this, we need to export the fields, and we have to insert an anonymous or blank field that covers the skipped bytes:

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

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

Having the above type, we can read all of it in one step like this:

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)

输出类似于,除了它还会显示匿名字段(在转到游乐场上尝试)a>):

Output is similar, except that it also displays the anonymous field (try it on the Go Playground):

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

请参阅相关答案:为什么要使用数组而不是切片?

您提到 input 切片是通过读取文件获得的.请注意,您无需先读取文件,例如 os.File 实现 io.Reader ,甚至是 io.ReadSeeker ,这意味着您可以直接从中读取内容,请参见创建 ReadSeeker 部分.您也可以直接应用 encoding/binary 解决方案,因为我们也在该解决方案中使用了阅读器.

You mentioned your input slice is from reading a file. Note that you do not need to read the file prior, as os.File implements io.Reader, even io.ReadSeeker, which means you can read from it directly, see the Creating a ReadSeeker section. You can also directly apply the encoding/binary solution, as we used a reader in that solution too.

这篇关于如何在切片上查找而从切片复制到阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆