go 文件读取和文件实时监控

战神悟空 · · 4236 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

package main

import (
    "bufio"
    "io"
    "io/ioutil"
    "log"
    "os"
    "time"
)

// 一次性读取
func ReadAll(filePth string) ([]byte, error) {
    f, err := os.Open(filePth)
    if err != nil {
        return nil, err
    }
    defer f.Close()
    /*
    ReadAll从r读取数据直到EOF或遇到error,返回读取的数据和遇到的错误。
    成功的调用返回的err为nil而非EOF。
    因为本函数定义为读取r直到EOF,它不会将读取返回的EOF视为应报告的错误。
     */
    return ioutil.ReadAll(f)
}

// 分块读取 可在速度和内存占用之间取得很好的平衡。
func ReadBlock(filePth string, bufSize int, hookfn func([]byte)) error {
    f, err := os.Open(filePth)
    if err != nil {
        return err
    }
    defer f.Close()

    buf := make([]byte, bufSize) //一次读取多少个字节
    /*
    NewReader创建一个具有默认大小缓冲、从r读取的*Reader。
     */
    bfRd := bufio.NewReader(f)
    for {
        n, err := bfRd.Read(buf)
        hookfn(buf[:n]) // n 是成功读取字节数

        if err != nil { //遇到任何错误立即返回,并忽略 EOF 错误信息
            if err == io.EOF {
                return nil
            }
            return err
        }
    }

    return nil
}

// 输出到控制台
func processTask(line []byte) {
    os.Stdout.Write(line)
    //fmt.Println(string(line))
}

// 逐行读取
func ReadLine(filePth string, hookfn func([]byte)) error {
    f, err := os.Open(filePth)
    if err != nil {
        return err
    }
    defer f.Close()

    bfRd := bufio.NewReader(f)
    for {
        line, err := bfRd.ReadBytes('\n')
        hookfn(line)
        if err != nil {
            if err == io.EOF {
                return nil
            }
            return err
        }
    }
    return nil
}

// 文件监控
func FileMonitoring(filePth string, hookfn func([]byte)) {
    f, err := os.Open(filePth)
    if err != nil {
        log.Fatalln(err)
    }
    defer f.Close()

    rd := bufio.NewReader(f)
    f.Seek(0, 2)
    for {
        line, err := rd.ReadBytes('\n')
        // 如果是文件末尾不返回
        if err == io.EOF {
            time.Sleep(500 * time.Millisecond)
            continue;
        } else if err != nil {
            log.Fatalln(err)
        }
        go hookfn(line)
    }

}
func main() {

    /*
    一次性读取
     */

    // 直接读取文件,无需打开句柄
    /*
    ret,err:=ioutil.ReadFile("/usr/local/nginx/logs/access.log")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(string(ret))
    */

    // 一次性读取
    /*
    ret, err := ReadAll("/usr/local/nginx/logs/access.log")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(string(ret))
    */

    // 分块读取
    /*
    ReadBlock("/usr/local/nginx/logs/access.log", 10000, processTask)
    */

    // 逐行读取
    /*
    ReadLine("/usr/local/nginx/logs/access.log", processTask)
    */

    // 示例 日志实时监控
    FileMonitoring("/usr/local/nginx/logs/access.log", processTask)

}

参考:
# Go -- 读取文件内容

Golang标准库文档


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:战神悟空

查看原文:go 文件读取和文件实时监控

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4236 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传