Go语言读文件的几种方法

2018-03-05  本文已影响0人  高稚商de菌

Go语言中常用的几种文件读写的方法分别为os.Open、bufio和ioutil。下面比较的直接调用File对象的Read函数、bufio的NewReader函数和ioutil的ReadAll的性能

package main
import (
    "fmt"
    "time"
    "os"
    "bufio"
    "io/ioutil"
)

// os.Open
func read1(filepath string) string {
    f, err := os.Open(filepath)
    if err != nil{  
        panic(err)  
    }
    defer f.Close()
    chunks := make([]byte,1024,1024)
    buf := make([]byte,1024)
    for {
        n, err := f.Read(buf)
        if err != nil || 0 == n {
            break
        }
        chunks = append(chunks, buf[:n]...)
    }
    return string(chunks)
}

// bufio
func read2(filepath string) string {
    file, err := os.Open(filepath)
    if err != nil{  
        panic(err)  
    }
    defer file.Close()
    chunks := make([]byte,1024,1024)
    f := bufio.NewReader(file)
    buf := make([]byte,1024)
    for {
        n, err := f.Read(buf)
        if err != nil || 0 == n {
            break
        }
        chunks = append(chunks, buf[:n]...)
    }
    return string(chunks)
}

// ioutil
func read3(filepath string) string {
    file, err := os.Open(filepath)
    if err != nil{  
        panic(err)  
    }
    defer file.Close()
    f, _ := ioutil.ReadAll(file)
    txt := string(f)
    return txt
}

func main() {
    filepath := "somefile.txt"
    t1 := time.Now()
    read1(filepath)
    elapsed1 := time.Since(t1)
    fmt.Println("cost ", elapsed1)
    t2 := time.Now()
    read2(filepath)
    elapsed2 := time.Since(t2)
    fmt.Println("cost ", elapsed2)
    t3 := time.Now()
    read3(filepath)
    elapsed3 := time.Since(t3)
    fmt.Println("cost ", elapsed3)
}

文件大小为48.47M,结果为

cost  222.050377ms
cost  111.779435ms
cost  82.178851ms

具体的性能差异,涉及到源码层面了。应该和源码中使用的buffer和系统调用中使用的buffer有关(是不是这两处的buffer还不一样呢,有空研究一下)。理论上说,系统调用读文件读的缓存区越大,调用次数越少,耗时越少。参考https://segmentfault.com/a/1190000011680507

使用时,根据需求选择:如果需要一次性读取,用ioutil.ReadFile和ioutil.ReadAll方便;如果需要分块或分行,用bufio的Read、ReadString或者ReadLine更加方便;如果是大文件读写的话,用bufio。

上一篇下一篇

猜你喜欢

热点阅读