golang 在#golang中逐行读取文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 在#golang中逐行读取文件相关的知识,希望对你有一定的参考价值。

package main

import (
	"bufio"
	"os"
)

// reads the file line by line.
func lineByLine(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		_ = line
		// do work
	}
	// more work
	return nil
}

Golang逐行读取大文件性能对比



前 言 

BUFIO 是什么?

BUFIO 是用来驱动 I/O 列内的专用时钟网络,这个专用的时钟网络独立于全局时钟资源,适合采集源同步数据。BUFIO 只能由位于同一时钟区域的 Clock-Capable I/O驱动。一个时钟区域有4个 BURIO,其中的2个可以驱动相邻区域的 I/O 时钟网络。BUFIO 不能驱动逻辑资源(CLB、BRAM等),因为 I/O 时钟网络只存在于 I/O 列中。


简单点就是:

  • bufio 包实现了带缓存的  I/O 操作

  • 它封装一个 io.Reader 或 io.Writer 对象

  • 使其具有缓存和一些文本读写功能


本文主要来对比一下 BUFIO 中的 ReadString 和 ReadLine 函数的性能。


注:测试代码忽略读取内容和错误处理


ReadString 函数


ReadString 代码:

func ReadString(filename string) {
    f, _ := os.Open(filename)
    defer f.Close()
    r := bufio.NewReader(f)
    for {
        _, err := r.ReadString('\n') 
        if err != nil {
            break
        }
    }
}


ReadLine  函数

ReadLine 代码:

func ReadLine(filename string) {    f, _ := os.Open(filename)    defer f.Close()    r := bufio.NewReader(f)    for {        _, err := readLine(r)        if err != nil {            break        }    } }


此函数主要解决单行字节数大于4096的情况

func readLine(r *bufio.Reader) (string, error) {
    line, isprefix, err := r.ReadLine()
    for isprefix && err == nil {
        var bs []byte
        bs, isprefix, err = r.ReadLine()
        line = append(line, bs...)
    }
    return string(line), err
}

注: 测试文件 log 每行字节数均大于4096


性 能  对 比

以上两种方式分别读取10G/20G/30G文件的耗时如下:


读取10G文件耗时

readstring:30.717832767s
readline:27.358268244s

读取20G文件耗时

readstring:59.937901346s
readline:54.871384854s

读取30G文件耗时

readstring:1m21.657831495s readline:1m13.222376352s


得 出 结 论

ReadLine 读取文件更快,原因是由于 ReadString 后端调用 ReadBytes,而 ReadBytes 多次使用 copy 方法造成大量耗时。

 

测试代码如下:

package main import (    "bufio"    "fmt"    "os"    "time" )
func main() {    filename := "./log"    s := time.Now()    ReadString(filename)    e1 := time.Now()    fmt.Printf("readstring:%v\n", e1.Sub(s))    ReadLine(filename)    e2 := time.Now()    fmt.Printf("readline:%v\n", e2.Sub(e1)) }
func ReadString(filename string) {    f, _ := os.Open(filename)    defer f.Close()    r := bufio.NewReader(f)    for {        _, err := r.ReadString('\n') //忽略内容        if err != nil {            break        }    } }
func ReadLine(filename string) {    f, _ := os.Open(filename)    defer f.Close()    r := bufio.NewReader(f)    for {        _, err := readLine(r)        if err != nil {            break        }    } }
func readLine(r *bufio.Reader) (string, error) {    line, isprefix, err := r.ReadLine()    for isprefix && err == nil {        var bs []byte        bs, isprefix, err = r.ReadLine()        line = append(line, bs...)    }    return string(line), err }



Golang 实战班第2期火热报名进行中


招生要求:


有Linux基础,有志于使用 Go 语言做分布式系统编程的人员,想往系统架构师方向发展的同学。BAT 架构师带你一起飞。


课程内容:


  • Golang入门

  • Golang程序结构

  • Golang的基础数据类型

  • Golang复合数据类型

  • Golang的函数

  • Golang的方法

  • Golang的接口

  • Golang的协程和Channel

  • Golang基于共享变量的并发

  • Golang包和工具



上课模式:网络直播班    线下面授班


咨询报名联系:

QQ(1):979950755    小月   

QQ(2):279312229    ada   

WeChat : 1902433859   小月

WeChat : 1251743084   小单


开课时间9月23日(周六)


课程大纲http://51reboot.com/course/go/

(阅读原文,即可跳转)



以上是关于golang 在#golang中逐行读取文件的主要内容,如果未能解决你的问题,请参考以下文章

golang 逐行读取文件

Golang逐行读取大文件性能对比

在 Go 中逐行读取文件

在 Swift 中逐行读取文本文件?

如何在Shell脚本中逐行读取文件

如何在 Julia 中逐行读取文件?