gpt4 book ai didi

go - 在 Golang 中读取/复制从 `io.Reader` 到 `io.Writer` 的特定数量的字节,或者如果超过特定字节限制则返回错误?

转载 作者:IT王子 更新时间:2023-10-29 01:42:00 24 4
gpt4 key购买 nike

我有一个 io.Reader在 Golang 中,我想在运行 io.Copy() 之前或运行时仔细检查其数据大小是否低于预定的最大值使用 io.Writer 将其保存到磁盘.

由于文件数据在io.Reader理论上可能会很大,如果可以避免的话,我想尽量减少这里的内存使用和处理。
我认为没有类似 io.CopyLessThanOrEqualToThisManyBytesOrReturnError() 的功能,但我确实注意到 io.ReadFull()如果没有足够的字节来填充提供的缓冲区,可以执行相反的操作以返回错误。

有没有人能解决这个问题?


编辑:
澄清一下,复制一小部分数据是不行的。它要么在超过阈值时失败,要么在低于阈值时工作。

最佳答案

因为 io.Reader 接口(interface)不知道底层数据的大小或长度,所以这个问题只有一个解决方案:

您可以使用一个最大大小为 nMax(预定最大值)+1 的缓冲区,并且在每次调用您的 CopyLessThanOrEqualToThisManyBytesOrReturnError 函数时,在此函数读取输入并对其进行缓冲,并检查此缓冲区长度,如果它小于或等于 nMax 则执行 io.Write,否则返回错误:

const nMax = 5 // your predetermined maximum

func CopyLessThanOrEqualToThisManyBytesOrReturnError(r io.Reader, w io.Writer) error {
var buf = make([]byte, nMax+1)
nRead, e := io.ReadFull(r, buf)
if nRead > 0 && nRead <= nMax {
w.Write(buf[:nRead])
return nil
}
if nRead > nMax {
return fmt.Errorf("there is more data")
}
return e
}

像这个不使用 string 的工作示例代码:

package main

import (
"fmt"
"io"
"os"
"strings"
)

const nMax = 5 // your predetermined maximum

func CopyLessThanOrEqualToThisManyBytesOrReturnError(r io.Reader, w io.Writer) error {
var buf = make([]byte, nMax+1)
nRead, e := io.ReadFull(r, buf)
if nRead > 0 && nRead <= nMax {
w.Write(buf[:nRead])
return nil
}
if nRead > nMax {
return fmt.Errorf("there is more data")
}
return e
}

func main() {
r := strings.NewReader("123456789")
err := CopyLessThanOrEqualToThisManyBytesOrReturnError(r, os.Stdout)
if err != nil {
fmt.Println(err) // there is more data
}

r = strings.NewReader("123\n")
err = CopyLessThanOrEqualToThisManyBytesOrReturnError(r, os.Stdout) // 123
if err != nil {
fmt.Println(err)
}

r = strings.NewReader("")
err = CopyLessThanOrEqualToThisManyBytesOrReturnError(r, os.Stdout)
if err != nil {
fmt.Println(err) // EOF
}
}

输出:

there is more data
123
EOF

工作示例代码,使用文件:

package main

import (
"fmt"
"io"
"os"
)

const nMax = 5 // your predetermined maximum

func CopyLessThanOrEqualToThisManyBytesOrReturnError(r io.Reader, w io.Writer) error {
var buf = make([]byte, nMax+1)
nRead, e := io.ReadFull(r, buf)
if nRead > 0 && nRead <= nMax {
w.Write(buf[:nRead])
return nil
}
if nRead > nMax {
return fmt.Errorf("there is more data")
}
return e
}

func main() {
r, err := os.Open("input.bin")
if err != nil {
panic(err)
}
defer r.Close()

w, err := os.Create("output.bin")
if err != nil {
panic(err)
}
defer w.Close()

err = CopyLessThanOrEqualToThisManyBytesOrReturnError(r, w)
if err != nil {
fmt.Println(err)
}
fmt.Println("Done.")
}

工作示例代码,使用 []byte:

package main

import (
"bytes"
"fmt"
"io"
)

const nMax = 5 // your predetermined maximum

func CopyLessThanOrEqualToThisManyBytesOrReturnError(r io.Reader, w io.Writer) error {
var buf = make([]byte, nMax+1)
nRead, e := io.ReadFull(r, buf)
if nRead > 0 && nRead <= nMax {
w.Write(buf[:nRead])
return nil
}
if nRead > nMax {
return fmt.Errorf("there is more data")
}
return e
}

func main() {
bs := []byte{1, 2, 3, 4, 5}
r := bytes.NewReader(bs)

w := &bytes.Buffer{}

err := CopyLessThanOrEqualToThisManyBytesOrReturnError(r, w)
if err != nil {
fmt.Println(err)
}

fmt.Println("Done.")
fmt.Println(w.Bytes())
}

输出:

Done.
[1 2 3 4 5]

关于go - 在 Golang 中读取/复制从 `io.Reader` 到 `io.Writer` 的特定数量的字节,或者如果超过特定字节限制则返回错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39050562/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com