Golang在读取YAML文件时如何截取切片进行反序列化

Golang在读取YAML文件时如何截取切片进行反序列化 我遇到了以下问题:

我正在使用 go-git 在内存中检出代码仓库。

然后,我使用 billy 包打开一个文件,并将其读取到一个 byte 切片中(因为它实现了 io.Reader 接口)。

file, err := fs.Open("releases/redash.yaml")

	if err != nil {
		log.Fatalf(err.Error())
	}

	data := make([]byte, 10000)
	_, err = file.Read(data)
	if err != nil {
		log.Fatalf("ERROR reading file")
	}
	err = yaml.Unmarshal(data, &v)
	if err != nil {
		log.Fatalf("ERROR Unmarshaling yaml\n", err)
	}
	fmt.Println(string(data))
}

上述代码失败了:

2020/02/06 12:58:45 ERROR Unmarshaling yaml yaml: control characters are not allowed exit status 1

根据我的理解,这是由于 data 缓冲区包含额外的/零值字符,yaml 尝试解析这些字符并抛出错误。

鉴于 billy.File 不允许我对它使用 ioutil.ReadFile,有没有办法解决这个问题?(例如,将 data 修剪到适当的长度?——我无法提前知道文件的确切长度,以便实例化一个大小合适的缓冲区)


更多关于Golang在读取YAML文件时如何截取切片进行反序列化的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

谢谢。

你能提供一个如何使用 fileRead 的例子吗?你发布的指向 io.Reader 的链接不包含这个方法(除非我漏掉了)。

更多关于Golang在读取YAML文件时如何截取切片进行反序列化的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


据我理解,这是由于 data 缓冲区包含额外的/零值字符

你是怎么知道的?是哪些字符?

没关系,我明白了

	data := make([]byte, 10000)
	n, err := file.Read(data)
	data = data[:n]

如果我执行 fmt.Println(data),我会在末尾得到大量的 0

我也从这个 Stack Overflow 帖子中得到了这个方向的提示。

file.Read 会返回读取的字节数,而你忽略了这一点。这个信息应该能帮助你向 yaml.Unmarshal 传递 data 的适当切片。

func main() {
    fmt.Println("hello world")
}

你可以通过读取文件的实际长度来避免缓冲区中的多余零值。使用 io.ReadFull 或读取直到 io.EOF 来获取确切的字节数,然后只反序列化有效部分。以下是修改后的代码示例:

import (
    "io"
    "log"
    "gopkg.in/yaml.v3"
)

file, err := fs.Open("releases/redash.yaml")
if err != nil {
    log.Fatalf(err.Error())
}
defer file.Close()

// 读取整个文件内容
data, err := io.ReadAll(file)
if err != nil {
    log.Fatalf("ERROR reading file: %v", err)
}

var v YourStructType
if err := yaml.Unmarshal(data, &v); err != nil {
    log.Fatalf("ERROR Unmarshaling yaml: %v", err)
}

如果文件较大且想避免一次性读取全部内容,可以预先获取文件大小:

info, err := file.Stat()
if err != nil {
    log.Fatalf("ERROR getting file info: %v", err)
}
data := make([]byte, info.Size())
n, err := io.ReadFull(file, data)
if err != nil && err != io.EOF {
    log.Fatalf("ERROR reading file: %v", err)
}
data = data[:n] // 截取实际读取的字节

这两种方法都确保 yaml.Unmarshal 只处理有效的文件内容,不会包含缓冲区中的零值。

回到顶部