如何在golang中使用samll ram读取大型文件?

如何在golang中使用samll ram读取大型文件?,go,readfile,Go,Readfile,我有这样的文档,我想在循环中读取每个5GB大小的文件,我尝试了一些方法,例如(file,err:=ioutil.ReadFile(filename)),但它会将整个文件加载到内存中。我使用这个函数加载文件: func visit(files *[]string) filepath.WalkFunc { return func(path string, info os.FileInfo, err error) error { if err != nil {

我有这样的文档,我想在循环中读取每个5GB大小的文件,我尝试了一些方法,例如(file,err:=ioutil.ReadFile(filename)),但它会将整个文件加载到内存中。我使用这个函数加载文件:

func visit(files *[]string) filepath.WalkFunc {
    return func(path string, info os.FileInfo, err error) error {
        if err != nil {
            log.Fatal(err)
        }
        *files = append(*files, path)
        return nil
    }
}
对于我使用的读取文件:

file, err := os.Open("file")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    buf := make([]byte,10*1024)
    for {
        n, err := file.Read(buf)
        if n > 0 {
            fmt.Print(buf[:n])
        }
        if err == io.EOF {
            break
        }
我想从buf解析数据

err = xml.Unmarshal(buf, &m)
if err != nil {
    log.Fatal(err)
}
fmt.Println(m)
m是:

在func main中:

func main() {
    var files []string
    root := "/folder/files"
    err := filepath.Walk(root, visit(&files))
    if err != nil {
        panic(err)
    }   
    for _, file := range files {
但执行时间太长了,我应该怎么做才能加快这个过程? 我在第496行得到一个错误XML语法错误:意外的EOF。
在这种情况下,并发可能很有用?

以下是一些可复制的基准测试结果:

固态硬盘:

硬盘驱动器:

硬盘驱动器:




您的可复制基准测试结果是什么?

答案完全取决于您想对文件执行什么操作。读取大文件可能需要很长时间。你到底期待什么?你得到了什么?你试过更大的缓冲区吗?您是否尝试过使用
bufio
?在处理大型文件时,您通常希望对其进行流式处理-读取一些(相对)较小的块,执行您需要的任何处理,然后读取下一个块,因此在任何给定时间内存中只有一个块。但是,正如Flimzy所说,如果不知道您在这里实际想要实现什么,就不可能更具体。两个硬盘之间的区别是什么,只是两次运行?
func main() {
    var files []string
    root := "/folder/files"
    err := filepath.Walk(root, visit(&files))
    if err != nil {
        panic(err)
    }   
    for _, file := range files {
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ go build readfile.go && time ./readfile
/home/peter/Downloads/ubuntu-mate-18.10-desktop-amd64.iso is 2103607296 bytes
real    0m2.839s
user    0m0.283s
sys     0m1.064s
$ 
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ go build readfile.go && time ./readfile
/home/peter/Downloads/ubuntu-mate-18.10-desktop-amd64.iso is 2103607296 bytes
real    0m14.194s
user    0m0.627s
sys     0m2.880s
$ 
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
3
$ go build readfile.go && time ./readfile
/home/peter/Downloads/ubuntu-mate-18.10-desktop-amd64.iso is 2103607296 bytes
real    0m16.627s
user    0m0.431s
sys     0m1.608s
$ 
package main

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

func readFile(fName string) (int64, error) {
    f, err := os.Open(fName)
    if err != nil {
        return 0, err
    }
    defer f.Close()
    r := bufio.NewReader(f)

    nr := int64(0)
    buf := make([]byte, 0, 4*1024)
    for {
        n, err := r.Read(buf[:cap(buf)])
        buf = buf[:n]
        if n == 0 {
            if err == nil {
                continue
            }
            if err == io.EOF {
                break
            }
            return nr, err
        }

        // Do something with buf
        nr += int64(len(buf))

        if err != nil && err != io.EOF {
            return nr, err
        }
    }
    return nr, nil
}

func main() {
    fName := `/home/peter/Downloads/ubuntu-mate-18.10-desktop-amd64.iso`
    if len(os.Args) > 1 {
        fName = os.Args[1]
    }
    nr, err := readFile(fName)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }
    fmt.Printf("%s is %d bytes\n", fName, nr)
}