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

【问题】最近想在一个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

相关推荐

  1. Go读取文件n思路

    2024-04-22 11:46:04       40 阅读
  2. Go 读取文件

    2024-04-22 11:46:04       32 阅读
  3. 如何读取文件最后一并解析

    2024-04-22 11:46:04       53 阅读
  4. Go语言自给自足:编译自身神奇

    2024-04-22 11:46:04       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-22 11:46:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-22 11:46:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-22 11:46:04       87 阅读
  4. Python语言-面向对象

    2024-04-22 11:46:04       96 阅读

热门阅读

  1. 聚合支付的代付业务详解

    2024-04-22 11:46:04       41 阅读
  2. 大模型prompt engineering api开发

    2024-04-22 11:46:04       130 阅读
  3. torch.where()中并行方式的实现

    2024-04-22 11:46:04       82 阅读
  4. http和https区别与上网过程

    2024-04-22 11:46:04       35 阅读
  5. SQLite去除.db-shm和.db-wal文件【已解决】

    2024-04-22 11:46:04       34 阅读
  6. Spring Boot 中整合 Redisson 实现分布式锁

    2024-04-22 11:46:04       39 阅读
  7. 三年经验!你还不知道KVM虚拟化技术???

    2024-04-22 11:46:04       42 阅读
  8. python内存泄漏解决

    2024-04-22 11:46:04       35 阅读
  9. 工程师每日刷题-7

    2024-04-22 11:46:04       40 阅读
  10. Vue模版语法(初学Vue之v-指令语法)

    2024-04-22 11:46:04       40 阅读
  11. 什么是 ORM(对象关系映射)

    2024-04-22 11:46:04       32 阅读
  12. web开发

    web开发

    2024-04-22 11:46:04      39 阅读
  13. 【数学建模】建筑工地开工问题

    2024-04-22 11:46:04       43 阅读