19

「tail-f」と同じ機能を持つ小さなコードを C++ で作成したいと考えています。テキスト ファイル内の新しい行を監視し、それらを標準出力に表示します。

アイデアは、ファイルを監視するスレッドを持つことです

毎回ファイルを開いたり閉じたりせずに簡単に行う方法はありますか?

4

6 に答える 6

15

ファイルを読み続けるだけです。読み取りに失敗した場合は、何もしません。開閉を繰り返す必要はありません。ただし、オペレーティング システム固有の機能を使用してファイルを監視する方がはるかに効率的であることがわかります (OS が提供している場合)。

于 2010-04-23T07:51:01.137 に答える
15

Linux ではinotifyを、Mac OS では kqueue を見てください。

Inotifyは Linux カーネル サブシステムであり、ファイルのイベントをサブスクライブできるようにし、ファイルでイベントが発生したときにアプリケーションに報告します。

于 2010-04-23T08:01:35.663 に答える
2

以下のコードが getc の代わりに getline を使用し、新しい行をスキップしないことを除いて、https: //stackoverflow.com/a/7514051/44729 と同じです。

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

using namespace std;

static int last_position=0;
// read file untill new line
// save position

int find_new_text(ifstream &infile) {

   infile.seekg(0,ios::end);
   int filesize = infile.tellg();

   // check if the new file started
   if(filesize < last_position){
      last_position=0;
   }  
   // read file from last position  untill new line is found 

   for(int n=last_position;n<filesize;n++) {

      infile.seekg( last_position,ios::beg);
      char  test[256]; 
      infile.getline(test, 256);
      last_position = infile.tellg();
      cout << "Char: "  << test <<"Last position " << last_position<<  endl;
      // end of file 
      if(filesize == last_position){
        return filesize;
      } 

  }

  return 0;
}


int main() {

  for(;;) {
    std::ifstream infile("filename");
    int current_position = find_new_text(infile);
    sleep(1);
  } 

} 
于 2013-09-18T19:38:57.603 に答える
1

私はこれをPerlのマニュアルの1つで読みましたが、標準のCに簡単に変換でき、次に標準のCに変換できますistream

   seek FILEHANDLE,POSITION,WHENCE
      Sets FILEHANDLE's position, just like the "fseek" call of
      "stdio".  
       <...>
       A WHENCE of 1 ("SEEK_CUR") is useful for not moving the file 
       position:

           seek(TEST,0,1);

       This is also useful for applications emulating "tail -f".  Once
       you hit EOF on your read, and then sleep for a while, you might
       have to stick in a seek() to reset things.  The "seek" doesn't
       change the current position, but it does clear the end-of-file
       condition on the handle, so that the next "<FILE>" makes Perl
       try again to read something.  We hope.

私が覚えている限り、fseekと呼ばれていiostream::seekgます。したがって、基本的に同じことを行う必要があります。ファイルの終わりまでシークしてから、スリープしてios_base::curフラグを付けてもう一度シークし、ファイルの終わりを更新して、さらにデータを読み取ります。

ingの代わりに、他の回答で提案されているように、ファイルが更新/クローズされるまで正確にスリープ(実際にはエミュレートされたファイルからの読み取り中にブロック)sleepするためにinotifyを使用できます。ただし、これはLinux固有であり、標準のC++ではありません。

于 2010-04-23T08:44:54.547 に答える
1

これも実装する必要がありました。標準 C++ で簡単なハックを書きました。ハックは、ファイル内の最後の 0x0A (改行文字) を検索し、最後の改行値がより大きな値になると、その改行に続くすべてのデータを出力します。コードは次のとおりです。

#include <iostream>
#include <string>
#include <fstream>

using namespace std;


int find_last_linefeed(ifstream &infile) {

  infile.seekg(0,ios::end);
  int filesize = infile.tellg();

  for(int n=1;n<filesize;n++) {
    infile.seekg(filesize-n-1,ios::beg);

    char c;
    infile.get(c);

    if(c == 0x0A) return infile.tellg();
  }
}


int main() {


  int last_position=-1;
  for(;;) {

    ifstream infile("testfile");
    int position = find_last_linefeed(infile);

    if(position > last_position) {
      infile.seekg(position,ios::beg);
      string in;
      infile >> in;
      cout << in << endl;
    }
    last_position=position;

    sleep(1);
  }

}
于 2011-09-22T11:32:19.107 に答える