如何有效地对文件进行多次写入

时间:2018-12-10 06:49:00

标签: go data-structures

我需要在Go中向文件写入多行。这些行将通过另一种方法生成。因此,要写入文件,我想到写入文件的行数与行数一样多。但是写入文件是一项昂贵的操作。我正在考虑一种非常乐观的写入文件的方式。我在这里可以使用什么数据结构?

1 个答案:

答案 0 :(得分:2)

要摊销操作系统文件的读写成本,请使用Go标准库bufio软件包。


以下是Go基准测试来说明这一点:bufio更快。

$ go test bufio_test.go -bench=.
goos: linux
goarch: amd64
BenchmarkBufioWrite-4    50     20887474 ns/op    6774811 B/op    147938 allocs/op
BenchmarkOSWrite-4        3    387543398 ns/op    6022413 B/op    104415 allocs/op
$

bufio_test.go

package main

import (
    "bufio"
    "io/ioutil"
    "os"
    "strings"
    "testing"
)

func BenchmarkBufioWrite(b *testing.B) {
    b.ReportAllocs()
    b.ResetTimer()
    for N := 0; N < b.N; N++ {
        out, err := ioutil.TempFile(``, `StackOverflow`)
        if err != nil {
            b.Fatal(err)
        }
        outName := out.Name()
        w := bufio.NewWriter(out)
        for _, line := range benchLines {
            _, err := w.Write([]byte(line))
            if err != nil {
                b.Fatal(err)
            }
        }
        err = w.Flush()
        if err != nil {
            b.Fatal(err)
        }
        err = out.Close()
        if err != nil {
            b.Fatal(err)
        }
        os.Remove(outName)
    }
}

func BenchmarkOSWrite(b *testing.B) {
    b.ReportAllocs()
    b.ResetTimer()
    for N := 0; N < b.N; N++ {
        out, err := ioutil.TempFile(``, `StackOverflow`)
        if err != nil {
            b.Fatal(err)
        }
        outName := out.Name()
        w := out
        for _, line := range benchLines {
            _, err := w.Write([]byte(line))
            if err != nil {
                b.Fatal(err)
            }
        }
        err = out.Close()
        if err != nil {
            b.Fatal(err)
        }
        os.Remove(outName)
    }
}

var benchLines = func() []string {
    // The Complete Works of William Shakespeare by William Shakespeare
    // http://www.gutenberg.org/files/100/100-0.txt
    data, err := ioutil.ReadFile(`/home/peter/shakespeare.100-0.txt`)
    if err != nil {
        panic(err)
    }
    return strings.Split(string(data), "\n")
}()