2012-08-01 22 views
9

I (tail -F ne benzer bir şey) büyüyor bir dosyadan okumaya çalışıyorum ama benim koduyla bazı sorunlar olmalı: hatları olmadanC++ 'da büyüyen bir metin dosyası nasıl okunur?

string log, logFile("test.log"); 
size_t p = 0; 

while(true) 
{ 
    ifstream ifs(logFile.c_str()); 

    ifs.seekg(p); //*1 

    while(ifs.eof() == false) 
    { 
     getline(ifs, log); 

     cout << log << endl; 

     p = ifs.tellg(); //*2 
    } 

    nanosleep(&pause, NULL); 
} 

// * 1 ve // ​​* 2, günlük dosyası sonuna kadar doğru okunur, ancak yeni satırlar eklenirse hiçbir şey olmaz.

Seekg ve tellg ile Dosyanın şu anki son konumunu saklamaya çalışıyorum, böylece yeniden açtığımda orada boğaza gidebilir ve nelerin eklendiğini okuyabilirim.

Kodumda neyin yanlış olduğunu bilmek istiyorum ve bu dosyayı aynı amaçla kapatmak ve yeniden açmak gerçekten gerekliyse.

Teşekkür ederiz.

cevap

12

döngü eof()tellg() döner -1 karşılaşıldığında yanlış olarak ve hemen olması gerekir getline() çağrısının eof() için bir onay yoktur. Değişim döngü için: -1p değeri 4294967295 ayarlı ediliyordu dönmek tellg() zaman p Ek olarak

while (getline(ifs, log)) 
{ 
    cout << log << endl; 
    p = ifs.tellg(); 
} 

, bir size_t olarak ilan edilir. Bu, seekg() dosyasının sonuna kadar ayarlandığı anlamına geliyordu. std::streamoff için p türünü değiştirin ve seekg() başarılı çağrısını onaylayın:

if (ifs.seekg(p)) 
{ 
    while (getline(ifs, log)) 
    { 
     cout << log << endl; 
     p = ifs.tellg(); 
    } 
} 

amaçla aynı dosyayı kapatıp yeniden açmak gerçekten gerekli olup olmadığını.

Hayır, gerekli değil ama akışından eof devlet clear() gerekir. Bu yöntem benim için sadakatle çalıştı

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

int main() 
{ 
    std::ifstream ifs("test.log"); 

    if (ifs.is_open()) 
    { 
     std::string line; 
     while (true) 
     { 
      while (std::getline(ifs, line)) std::cout << line << "\n"; 
      if (!ifs.eof()) break; // Ensure end of read was EOF. 
      ifs.clear(); 

      // You may want a sleep in here to avoid 
      // being a CPU hog. 
     } 
    } 

    return 0; 
} 
+0

düzgün çalışıyor. Teşekkür ederim. – Pietro

+0

Eğer ifstream nesnesini döngüde oluşturursam işe yarayıp yaramadığımı fark ettim. Eklenmiş olanı okumak için bir dosyayı kapatmak ve yeniden açmak gerekli midir? – Pietro

+0

@Pietro, bir sonraki okuma denemesinden önce 'ifs.clear()' diyerek 'ifstream' öğesinin eof durumunu temizlemeniz gerekir. Ben _think_ 'tellg()' ve 'seekg()' bu yaklaşımla gereksiz olacaktır. – hmjd

1

: Aşağıdaki yayınlanan bir kod düzeltilmiş sürümü için bir alternatiftir

#include <string> 
#include <chrono> 
#include <thread> 
#include <fstream> 
#include <iostream> 

int main(int, char* argv[]) 
{ 
    // open file passed in on command line (at end of file) 
    std::ifstream ifs(argv[1], std::ios::ate); 

    if(!ifs.is_open()) 
    { 
     std::cerr << "ERROR: opening log file: " << argv[1] << '\n'; 
     return 1; 
    } 

    // remember file position 
    std::ios::streampos gpos = ifs.tellg(); 

    std::string line; 
    bool done = false; 

    while(!done) 
    { 
     // try to read line 
     if(!std::getline(ifs, line) || ifs.eof()) 
     { 
      // if we fail, clear stream, return to beginning of line 
      ifs.clear(); 
      ifs.seekg(gpos); 

      // and wait to try again 
      std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
      continue; 
     } 

     // remember the position of the next line in case 
     // the next read fails 
     gpos = ifs.tellg(); 

     // process line here 
     std::cout << "line: " << line << std::endl; 
    } 
} 
0

Bu kod benim için çalışıyor: Şimdi

struct timespec pause; 
pause.tv_sec = 1; 
pause.tv_nsec = 0; 

std::ifstream ifs("test.log"); 
std::streamoff p; 

if(ifs.is_open()) 
{ 
    std::string line; 

    while(true) 
    { 
     if(ifs.seekg(p)) 
     { 
      while(std::getline(ifs, line)) 
      { 
       std::cout << line << std::endl; 
       p = ifs.tellg(); 
      } 
     } 

     ifs.clear(); 

     nanosleep(&pause, NULL); 
    } 
} 
İlgili konular