iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Golang 实现超大文件读取的两种方法
  • 464
分享到

Golang 实现超大文件读取的两种方法

2024-04-02 19:04:59 464人浏览 独家记忆
摘要

golang超大文件读取的两个方案 流处理方式 分片处理 去年的面试中我被问到超大文件你怎么处理,这个问题确实当时没多想,回来之后仔细研究和讨论了下这个问题,对大文件读取做了一个分析

golang超大文件读取的两个方案

流处理方式

分片处理

去年的面试中我被问到超大文件你怎么处理,这个问题确实当时没多想,回来之后仔细研究和讨论了下这个问题,对大文件读取做了一个分析

比如我们有一个log文件,运行了几年,有100G之大。按照我们之前的操作可能代码会这样写:


func ReadFile(filePath string) []byte{
    content, err := ioutil.ReadFile(filePath)
    if err != nil {
        log.Println("Read error")
    }
    return content
} 

上面的代码读取几兆的文件可以,但是如果大于你本身及其内存,那就直接翻车了。因为上面的代码,是把文件所有的内容全部都读取到内存之后返回,几兆的文件,你内存够大可以处理,但是一旦上几百兆的文件,就没那么好处理了。

那么,正确的方法有两种

第一个是使用流处理方式代码如下


func ReadFile(filePath string, handle func(string)) error {
    f, err := os.Open(filePath)
    defer f.Close()
    if err != nil {
        return err
    }
    buf := bufio.NewReader(f)
 
    for {
        line, err := buf.ReadLine("\n")
        line = strings.TrimSpace(line)
        handle(line)
        if err != nil {
            if err == io.EOF{
                return nil
            }
            return err
        }
        return nil
    }
}

第二个方案就是分片处理

当读取的是二进制文件,没有换行符的时候,使用下面的方案一样处理大文件


func ReadBigFile(fileName string, handle func([]byte)) error {
    f, err := os.Open(fileName)
    if err != nil {
        fmt.Println("can't opened this file")
        return err
    }
    defer f.Close()
    s := make([]byte, 4096)
    for {
        switch nr, err := f.Read(s[:]); true {
        case nr < 0:
            fmt.Fprintf(os.Stderr, "cat: error reading: %s\n

补充:golang 读取大文件处理sync.pool + bufio.NewReader(f)

看代码吧~

文件大小

在这里插入图片描述


package main
import (
	"bufio"
	"fmt"
	"io"
	//"math"
	"os"
	"strings"
	"sync"
	"time"
)
func main() {
	
	var (
		s time.Time //当前时间
		file *os.File
		fileStat os.FileInfo
		err error
		lastLineSize int64
	)
	s = time.Now()
	if file, err = os.Open("/Users/zhangsan/Downloads/log.txt");err != nil{
		fmt.Println(err)
	}
	defer func() {
		err = file.Close() //close after checking err
	}()
	//queryStartTime, err := time.Parse("2006-01-02T15:04:05.0000Z", startTimeArg)
	//if err != nil {
	//	fmt.Println("Could not able to parse the start time", startTimeArg)
	//	return
	//}
	//
	//queryFinishTime, err := time.Parse("2006-01-02T15:04:05.0000Z", finishTimeArg)
	//if err != nil {
	//	fmt.Println("Could not able to parse the finish time", finishTimeArg)
	//	return
	//}
	
	if fileStat, err = file.Stat();err != nil {
		return
	}
	fileSize := fileStat.Size()//72849354767
	offset := fileSize - 1
	//检测是不是都是空行 只有\n
	for {
		var (
			b []byte
			n int
			char string
		)
		b = make([]byte, 1)
		//从指定位置读取
		if n, err = file.ReadAt(b, offset);err != nil {
			fmt.Println("Error reading file ", err)
			break
		}
		char = string(b[0])
		if char == "\n" {
			break
		}
		offset--
		//获取一行的大小
		lastLineSize += int64(n)
	}
	var (
		lastLine []byte
		logSlice []string
		logSlice1 []string
	)
	//初始化一行大小的空间
	lastLine = make([]byte, lastLineSize)
	_, err = file.ReadAt(lastLine, offset)
	if err != nil {
		fmt.Println("Could not able to read last line with offset", offset, "and lastline size", lastLineSize)
		return
	}
	//根据条件进行区分
	logSlice = strings.Split(strings.Trim(string(lastLine),"\n"),"next_pay_date")
	logSlice1  = strings.Split(logSlice[1],"\"")
	if logSlice1[2] == "2021-06-15"{
		Process(file)
	}
	fmt.Println("\nTime taken - ", time.Since(s))
		fmt.Println(err)
}
func Process(f *os.File) error {
	//读取数据的key,减小GC压力
	linesPool := sync.Pool{New: func() interface{} {
		lines := make([]byte, 250*1024)
		return lines
	}}
	//读取回来的数据池
	stringPool := sync.Pool{New: func() interface{} {
		lines := ""
		return lines
	}}
	//一个文件对象本身是实现了io.Reader的 使用bufio.NewReader去初始化一个Reader对象,存在buffer中的,读取一次就会被清空
	r := bufio.NewReader(f) //
	//设置读取缓冲池大小 默认16
	r = bufio.NewReaderSize(r,250 *1024)
	var wg sync.WaitGroup
	for {
		buf := linesPool.Get().([]byte)
		//读取Reader对象中的内容到[]byte类型的buf中
		n, err := r.Read(buf)
		buf = buf[:n]
		if n == 0 {
			if err != nil {
				fmt.Println(err)
				break
			}
			if err == io.EOF {
				break
			}
			return err
		}
		//补齐剩下没满足的剩余
		nextUntillNewline, err := r.ReadBytes('\n')
		//fmt.Println(string(nextUntillNewline))
		if err != io.EOF {
			buf = append(buf, nextUntillNewline...)
		}
		wg.Add(1)
		Go func() {
			ProcessChunk(buf, &linesPool, &stringPool)
			wg.Done()
		}()
	}
	wg.Wait()
	return nil
}
func ProcessChunk(chunk []byte, linesPool *sync.Pool,stringPool *sync.Pool) {
//做相应的处理
}

执行


go run test2.go "2020-01-01T00:00:00.0000Z" "2020-02-02T00:00:00.0000Z" /Users/zhangsan/go/src/workspace/test/log.log

EOF
Time taken -  20.023517675s
<nil>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。如有错误或未考虑完全的地方,望不吝赐教。

您可能感兴趣的文档:

--结束END--

本文标题: Golang 实现超大文件读取的两种方法

本文链接: https://www.lsjlt.com/news/124729.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Golang 实现超大文件读取的两种方法
    Golang超大文件读取的两个方案 流处理方式 分片处理 去年的面试中我被问到超大文件你怎么处理,这个问题确实当时没多想,回来之后仔细研究和讨论了下这个问题,对大文件读取做了一个分析...
    99+
    2024-04-02
  • GoLang读取文件的10种方法实例
    目录一. 整个文件读入内存1.直接指定文化名读取1.1使用os.ReadFile函数读取文件2.先创建句柄再读取2.1使用os.OpenFile函数只读形式获取句柄2.2代码讲解二....
    99+
    2024-04-02
  • java读取excel文件的两种方法
    本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下方式一:借用 package com.ij34.util;import java.io.File; import java.io.IOExcept...
    99+
    2023-05-31
    java excel ava
  • Excel文件读取的两种方式
    1、Pandas库的读取操作 from pandas import read_excel dr=read_excel(filename,header) dr#dataframe数据 dw=DataFrams(data=dict,colum...
    99+
    2023-01-31
    两种 方式 文件
  • 怎么在Golang中读取超大文件
    怎么在Golang中读取超大文件?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。什么是golanggolang 是Google开发的一种静态强类型、编译型、并发型...
    99+
    2023-06-14
  • golang读取注释内容的两种方法
    在Go语言中,注释是一个重要的功能,一个良好的注释可以使代码更加易于理解和维护。但是,有时候我们需要在代码中读取注释。本文将介绍一些方法来实现这个目标。基本的注释读取方法在Go语言中,注释可以使用//和/ /来表示单行注释和多行注释。我们可...
    99+
    2023-05-14
  • Golang按行读取文件的三种方法小结
    目录1.使用 bufio.Scanner 读取文件2.使用 bufio.Reader 读取文件3.使用 bufio.Reader 的 ReadLine 读取文件4.go-huge-u...
    99+
    2023-05-17
    Golang 按行读取文件 Golang 按行读取
  • 用Shell实现逐行读取文件的4种方法
    这篇文章主要介绍“用Shell实现逐行读取文件的4种方法”,在日常操作中,相信很多人在用Shell实现逐行读取文件的4种方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”用Shell实现逐行读取文件的4种方法...
    99+
    2023-06-09
  • Golang文件读取操作:快速读取大文件的技巧
    Golang文件读取操作:快速读取大文件的技巧,需要具体代码示例 在Golang程序设计中,文件读取是一个非常常见的操作。但当需要读取大文件时,通常是一件比较耗费时间和资源的操作。因此,如何快速读取大文件是一...
    99+
    2024-01-19
    大文件 Golang 文件读取
  • Java读取文本文件的各种方法
    目录1、方法方法一、 使用BufferedReader类方法二、使用 FileReader 类方法三、使用 Scanner 类方法四、读取列表中的整个文件2、语法方法五、将文本文件读...
    99+
    2024-04-02
  • python文件读取read及readlines两种方法使用详解
    目录引言.read([size])方法.readlines()方法引言 with open() as 和open()都是打开,还没有读入文件 假设test.fa的内容如下图所示: A...
    99+
    2024-04-02
  • jsp 实现上传文件的两种方法
    在用Java开发企业器系统的使用,特别是涉及到与办公相关的软件开发的时候,文件的上传是客户经常要提到的要求.因此有 一套很好文件上传的解决办法也能方便大家在这一块的开发.........[@more@]在用Java开发企业器系统的使用,特别...
    99+
    2023-06-03
  • Python读取CSV文件的几种方法
    话不多说,开干!!! 目录 1. 使用 csv 模块 2.使用 numpy 库 3.使用pandas库 4.使用标准库中的 csv 模块 5.注意事项 1. 使用 csv 模块 (1)项目目录如下图所示: (2)代码如下: impor...
    99+
    2023-08-31
    python 开发语言 pandas numpy
  • GoLang读取文件的方法有哪些
    这篇文章主要介绍“GoLang读取文件的方法有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“GoLang读取文件的方法有哪些”文章能帮助大家解决问题。一. 整个文件读入内存直接将数据直接读取入内...
    99+
    2023-07-02
  • 实例讲解python读取各种文件的方法
    目录1.yaml文件2.CSV文件3.ini文件总结1.yaml文件 # house.yaml--------------------------------------------...
    99+
    2024-04-02
  • golang读取文件有哪些方法
    golang读取文件的方法:1、使用os包和os.Open函数;2、使用bufio包和Scanner类型;3、使用ioutil包和ReadFile函数;4、使用os/exec包和命令行工具组合读取文件内容。详细介绍:1、使用os包和os.O...
    99+
    2023-12-14
    Golang
  • C#获取文件名和文件路径的两种实现方式
    目录C#获取文件名和文件路径方法一方法二C#通过文件路径获取文件名小技巧C#获取文件名和文件路径 方法一 OpenFileDialog open = new OpenFileDia...
    99+
    2024-04-02
  • python实现单例的两种方法解读
    目录python 实现单例的方法第一种方法:使用基类第二种方法:使用装饰器python 单例对象单列模式总结python 实现单例的方法 第一种方法:使用基类 New 是真正创建实例...
    99+
    2023-03-02
    python实现单例 python单例 python单例方法
  • Python实现读取文件的方法总结
    目录序言1、方法介绍2、 默认读取3、处理一个文件4、处理批量文件5、读取与备份6、重定向替换7、进阶总结序言 哈喽兄弟们,今天咱们来了解一下 fileinput 。 说到filei...
    99+
    2024-04-02
  • SpringBoot读取Resource下文件的4种方法
    SpringBoot读取Resource下文件 最近在项目中涉及到Excle的导入功能,通常是我们定义完模板供用户下载,用户按照模板填写完后上传;这里待下载模板位置为resource...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作