duandgfh0506 2018-09-06 17:32
浏览 105

精确读取n个字节,除非EOF?

I'm using a function that returns an io.Reader to download a file from the Internet.

I want to process the file in exactly 2048 chunks until it's no longer possible because of EOF.

The io.ReadFull function is almost what I want:

buf := make([]byte, 2048)

for {
    if _, err := io.ReadFull(reader, buf); err == io.EOF {
        return io.ErrUnexpectedEOF
    } else if err != nil {
        return err
    }

    // Do processing on buf
}

The problem with this is that not all files are a multiple of 2048 bytes, so the last chunk may only be e.g. 500 bytes, io.ReadFull will therefore return ErrUnexpectedEOF and the last chunk is discarded.

A function name to summarize what I want could be io.ReadFullUnlessLastChunk, so ErrUnexpectedEOF is not returned if the reason that buf cannot be filled with 2048 bytes, is that the file is EOF after e.g. 500 bytes. However, in any other case ErrUnexpectedEOF should be returned as a problem has occured.

What could I do to accomplish this?

Another problem is that reading only 2048 bytes at the time directly from the network seems to have much overhead, if I could get 256 KB from network into a buffer, and then take the 2048 bytes I need from that buffer instead, that would be better.

  • 写回答

1条回答 默认 最新

  • dongxi5505 2018-09-06 20:02
    关注

    For example,

    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    func readChunks(r io.Reader) error {
        if _, ok := r.(*bufio.Reader); !ok {
            r = bufio.NewReader(r)
        }
        buf := make([]byte, 0, 2048)
        for {
            n, err := io.ReadFull(r, buf[:cap(buf)])
            buf = buf[:n]
            if err != nil {
                if err == io.EOF {
                    break
                }
                if err != io.ErrUnexpectedEOF {
                    return err
                }
            }
    
            // Process buf
            fmt.Println(len(buf))
    
        }
        return nil
    }
    
    func main() {
        fName := `test.file`
        f, err := os.Open(fName)
        if err != nil {
            fmt.Println(err)
            return
        }
        defer f.Close()
    
        err = readChunks(f)
        if err != nil {
            fmt.Println(err)
            return
        }
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 MATLAB运行显示错误,如何解决?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容
  • ¥15 UE5#if WITH_EDITOR导致打包的功能不可用
  • ¥15 关于#stm32#的问题:CANOpen的PDO同步传输问题
  • ¥20 yolov5自定义Prune报错,如何解决?
  • ¥15 电磁场的matlab仿真
  • ¥15 mars2d在vue3中的引入问题
  • ¥50 h5唤醒支付宝并跳转至向小荷包转账界面
  • ¥15 算法题:数的划分,用记忆化DFS做WA求调