Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 从末尾读取日志文件并获取特定字符串的偏移量_File_Go_Io - Fatal编程技术网

File 从末尾读取日志文件并获取特定字符串的偏移量

File 从末尾读取日志文件并获取特定字符串的偏移量,file,go,io,File,Go,Io,.例如。 1.日志文件 开始 第1行 第2行 第3行 结束 当我从一开始读取文件时,我能够得到第1行的查找位置 func getSeekLocation() int64 { start := int64(0) input, err := os.Open(logFile) if err != nil { fmt.Println(err) } if _, err := input.Seek(start, io.SeekStart); err

.例如。 1.日志文件

  • 开始
  • 第1行
  • 第2行
  • 第3行
  • 结束
当我从一开始读取文件时,我能够得到第1行的查找位置

func getSeekLocation() int64 {
    start := int64(0)
    input, err := os.Open(logFile)
    if err != nil {
        fmt.Println(err)
    }
    if _, err := input.Seek(start, io.SeekStart); err != nil {
        fmt.Println(err)
    }
    scanner := bufio.NewScanner(input)

    pos := start
    scanLines := func(data []byte, atEOF bool) (advance int, token []byte, 
    err error) {
        advance, token, err = bufio.ScanLines(data, atEOF)
        pos += int64(advance)
        return
    }
    scanner.Split(scanLines)
    for scanner.Scan() {
       if strings.Contains(scanner.Text(), "Line1") {
        break
       }
    }
    size, err := getFileSize()
    if err != nil {
        fmt.Println(err)
    }
    return size - pos
}
但这并不是解决问题的有效方法,因为随着文件大小的增加,获取位置的时间也会增加。
我想从EOF位置获得线路的位置,我认为这会更有效

注意:我优化并改进了以下解决方案,并将其作为库发布在此处:


使用作为源,不支持从任意位置查找和/或读取,因此无法从末端扫描线
bufio.Scanner
只能在读取输入之前的所有数据后读取输入的任何部分(也就是说,如果先读取文件的所有内容,则只能读取文件的结尾)

因此,我们需要一个定制的解决方案来实现这种功能。幸运的是,它支持从任意位置读取数据,因为它实现了和(它们中的任何一个都足以满足我们的需要)

返回从末尾开始向后的行的扫描仪 让我们构造一个
扫描器
,它从最后一行开始向后扫描行。为此,我们将使用一个
io.ReaderAt
。下面的实现使用一个内部缓冲区,从输入的末尾开始,数据被块读取到该缓冲区中。输入的大小也必须被传递(这基本上是我们想要开始读取的位置,不一定是结束位置)

使用它的示例:

func main() {
    scanner := NewScanner(strings.NewReader(src), len(src))
    for {
        line, pos, err := scanner.Line()
        if err != nil {
            fmt.Println("Error:", err)
            break
        }
        fmt.Printf("Line start: %2d, line: %s\n", pos, line)
    }
}

const src = `Start
Line1
Line2
Line3
End`
输出(在上尝试):

注意事项:

  • 上述
    扫描仪
    不限制行的最大长度,它处理所有行
  • 上述
    扫描仪
    处理
    \n
    \r\n
    行结束(由
    dropCR()
    函数确保)
  • 您可以传递任何起始位置,而不仅仅是大小/长度,并且将从那里执行列表行(续)
  • 上面的
    扫描仪
    不重用缓冲区,总是在需要时创建新的缓冲区。(预先)分配2个缓冲区就足够了,并明智地使用它们。实现将变得更加复杂,它将引入最大行长度限制
将其与文件一起使用 要将此
扫描仪
用于文件,可以使用
os.Open()
打开文件。请注意,
*文件
实现了
io.ReaderAt()
。然后,您可以使用获取有关文件()的信息,包括其大小(长度):

在一行中查找子字符串 如果要在一行中查找子字符串,只需使用上面的
扫描仪
,它返回每行的起始位置,从末尾读取行

您可以使用检查每行中的子字符串,这将返回行中的子字符串位置,如果找到,则将行开始位置添加到此行

假设我们正在寻找
“ine2”
子字符串(它是
“Line2”
行的一部分)。以下是如何做到这一点:

scanner := NewScanner(strings.NewReader(src), len(src))
what := "ine2"
for {
    line, pos, err := scanner.Line()
    if err != nil {
        fmt.Println("Error:", err)
        break
    }
    fmt.Printf("Line start: %2d, line: %s\n", pos, line)

    if i := strings.Index(line, what); i >= 0 {
        fmt.Printf("Found %q at line position: %d, global position: %d\n",
            what, i, pos+i)
        break
    }
}
输出(在上尝试):


可能的重复是第一次还是任何一次?从底部扫描表明是前者,但只是为了再次检查。@AlessandroSantini它应该会发现第一次出现。
Line start: 24, line: End
Line start: 18, line: Line3
Line start: 12, line: Line2
Line start:  6, line: Line1
Line start:  0, line: Start
Error: EOF
f, err := os.Open("a.txt")
if err != nil {
    panic(err)
}
fi, err := f.Stat()
if err != nil {
    panic(err)
}
defer f.Close()

scanner := NewScanner(f, int(fi.Size()))
scanner := NewScanner(strings.NewReader(src), len(src))
what := "ine2"
for {
    line, pos, err := scanner.Line()
    if err != nil {
        fmt.Println("Error:", err)
        break
    }
    fmt.Printf("Line start: %2d, line: %s\n", pos, line)

    if i := strings.Index(line, what); i >= 0 {
        fmt.Printf("Found %q at line position: %d, global position: %d\n",
            what, i, pos+i)
        break
    }
}
Line start: 24, line: End
Line start: 18, line: Line3
Line start: 12, line: Line2
Found "ine2" at line position: 1, global position: 13