Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.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
C++ 如何从不断更新的文件中读取和提取信息?_C++_C_Perl_Shell - Fatal编程技术网

C++ 如何从不断更新的文件中读取和提取信息?

C++ 如何从不断更新的文件中读取和提取信息?,c++,c,perl,shell,C++,C,Perl,Shell,以下是我计划为项目构建实用程序的方式: logdump将日志结果转储到文件log。如果文件已经存在,则结果将附加到现有结果(例如,如果每月创建一个新文件,则结果将附加到该月的同一文件) 提取读取日志结果文件,根据提供的参数提取相关结果 问题是我不想等待logdump完成写入log开始处理它。同样,我需要记住,直到我已经阅读了日志的地方,才能开始提取更多信息,这不是我想要做的 我需要实时结果,以便无论何时向日志结果文件添加内容,extract都将获得所需的结果 extract将执行的处理是通用的

以下是我计划为项目构建实用程序的方式:

  • logdump将日志结果转储到文件log。如果文件已经存在,则结果将附加到现有结果(例如,如果每月创建一个新文件,则结果将附加到该月的同一文件)

  • 提取读取日志结果文件,根据提供的参数提取相关结果

  • 问题是我不想等待logdump完成写入log开始处理它。同样,我需要记住,直到我已经阅读了日志的地方,才能开始提取更多信息,这不是我想要做的

  • 我需要实时结果,以便无论何时向日志结果文件添加内容,extract都将获得所需的结果

  • extract将执行的处理是通用的(取决于它的一些命令行参数),但肯定是逐行执行的

这包括在写入文件时读取文件,并在到达日志文件末尾后持续监视文件是否有新的更新


<强>我如何使用C或C++或shell脚本或perl?< /强>

< p> <代码>尾-f/COD>将从文件读取并监视它在EOF到达时的更新,而不是直接退出。这是一种“实时”读取日志文件的简单方法。可以简单到:

tail -f log.file | extract

或者
tail-n0-f
这样它只打印新行,而不是现有行。或者
tail-n+0-f
显示整个文件,然后继续更新。

用于此操作的传统unix工具是
tail-f
,它会一直读取附加到其参数的数据,直到将其终止。所以你可以

tail -c +1 -f log | extract
在unix世界中,从连续附加到文件的数据中读取数据被称为“拖尾”。在Perl中,模块执行相同的任务

use File::Tail;
my $log_file = File::Tail->new("log");
while (defined (my $log_line = $log_file->read)) {
    process_line($log_line);
}

使用
logdump的简单代理

#! /usr/bin/perl

use warnings;
use strict;

open my $fh, ">", "log" or die "$0: open: $!";
select $fh;
$| = 1;  # disable buffering

for (1 .. 10) {
  print $fh "message $_\n" or warn "$0: print: $!";
  sleep rand 5;
}
以及下面的
提取
框架,以获得所需的处理。当
logfile
遇到文件结尾时,
logfile.eof()
为true。调用
logfile.clear()

#include <iostream>
#include <fstream>
#include <cerrno>
#include <cstring>
#include <unistd.h>

int main(int argc, char *argv[])
{
  const char *path;
  if      (argc == 2) path = argv[1];
  else if (argc == 1) path = "log";
  else {
    std::cerr << "Usage: " << argv[0] << " [ log-file ]\n";
    return 1;
  }

  std::ifstream logfile(path);
  std::string line;
  next_line: while (std::getline(logfile, line))
    std::cout << argv[0] << ": extracted [" << line << "]\n";

  if (logfile.eof()) {
    sleep(3);
    logfile.clear();
    goto next_line;
  }
  else {
    std::cerr << argv[0] << ": " << path << ": " << std::strerror(errno) << '\n';
    return 1;
  }

  return 0;
}
最后,如果你坚持自己做举重,有一个:

如何在perl中实现tail-f? 初试

seek(GWFILE, 0, 1);
语句
seek(GWFILE,0,1)
不会更改当前位置,但会清除句柄上的文件结束条件,以便下一个
使Perl再次尝试读取某些内容

如果这不起作用(它依赖于stdio实现的特性),那么您需要类似这样的东西:

for (;;) {
  for ($curpos = tell(GWFILE); <GWFILE>; $curpos = tell(GWFILE)) {
    # search for some stuff and put it into files
  }
  # sleep for a while
  seek(GWFILE, $curpos, 0);  # seek to where we had been
}
(;;)的
{
对于($curpos=tell(GWFILE);$curpos=tell(GWFILE)){
#搜索一些东西并将其放入文件中
}
#睡一会儿
寻找(GWFILE,$curpos,0)#寻找我们曾经去过的地方
}
如果这仍然不起作用,请查看中的
clearr
方法,该方法重置句柄上的错误和文件结束状态

还有一个来自CPAN的模块


虽然这符合我的需要,有没有办法使用C或C++?@拉泽:你可以总是“欺骗”,并查看“黑客的满葩格”-源代码尾。IIRC,它是非常简单的C代码。看这里:在这些情况下,我尝试修改日志以转到数据库。那么你就很容易得到你还没有处理过的记录了。如果您还没有设计日志部分,那么这可能是一个不错的选择。
seek(GWFILE, 0, 1);
for (;;) {
  for ($curpos = tell(GWFILE); <GWFILE>; $curpos = tell(GWFILE)) {
    # search for some stuff and put it into files
  }
  # sleep for a while
  seek(GWFILE, $curpos, 0);  # seek to where we had been
}