Go读取文件n行的思路之旅

本文讨论了在10G大文件中读取最后100行数据的两种方法:双端队列适用于小文件,效率高;逆向读取适用于大文件,内存占用低。作者给出了具体实现步骤和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【问题】最近想在一个10G的文件上读取最后100行数据,用了多种方式去实现,发现还是逆向读取比较香一点
【方法】分别尝试了两种方式:双端队列和逆读文件
  在这里我就直接把结论放在文章前面

  • 双端队列:适用于文件数据不大的情况,效率会达到最高
  • 逆读文件:适用于大文件,会有不俗的读取速率,内存占用也不高

开始前,先亮一下【读取文件正常操作】

path := "/www/" + siteName + ".log"
num := 100
data := make([]string, 0, num)

file, err := os.Open(path)
if err != nil {
    return data
}
defer file.Close()
// 顺读日志信息
scanner := bufio.NewScanner(file)
for scanner.Scan() && len(data) < num {
    data = append(data, scanner.Text())
}

if err := scanner.Err(); err != nil {
    fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
return data

一、双端队列实现读取100行数据

data1 := list.New()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
    // 将新的行添加到队列的末尾
    data1.PushBack(scanner.Text())

    // 如果队列的大小超过100,从队列的头部移除元素
    if data1.Len() > num {
       e := data1.Front()
       data1.Remove(e)
    }
}

if err := scanner.Err(); err != nil {
    fmt.Fprintln(os.Stderr, "reading standard input:", err)
}

// 将队列转换为切片
res := make([]string, 0, num)
for e := data1.Front(); e != nil; e = e.Next() {
    res = append(res, e.Value.(string))
}

return res

二、逆向读取

  使用文件指针,从文件的末尾开始读取。我们可以使用os包的Seek函数来定位文件的末尾,然后逐行向上读取,直到读取到100行。

stats, statsErr := file.Stat()
if statsErr != nil {
    return nil
}

size := stats.Size()
lines := make([]string, 0, num)
buf := make([]byte, size)

for {
    readSize, err := file.ReadAt(buf, size-int64(len(buf)))
    if err != nil && err != io.EOF {
       break
    }

    size -= int64(readSize)

    for i := readSize - 1; i >= 0; i-- {
       if buf[i] == '\n' {
          lines = append(lines, string(buf[i+1:readSize]))
          readSize = i
          if len(lines) == num {
             return lines
          }
       }
    }

    if size == 0 {
       lines = append(lines, string(buf[:readSize]))
       break
    }

    if len(lines) >= num {
       break
    }

    if size < int64(len(buf)) {
       buf = make([]byte, size)
    }
}

return lines
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值