2012-08-01 36 views
9

मैं जो बढ़ रही है (tail -F क्या करता है करने के लिए कुछ इसी तरह) एक फ़ाइल से पढ़ने की कोशिश कर रहा हूँ, लेकिन मेरे कोड के साथ कुछ समस्या होना चाहिए:सी ++ में बढ़ती हुई टेक्स्ट फ़ाइल को कैसे पढ़ा जाए?

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 और // * 2, लॉग फ़ाइल सही ढंग से इसके अंत तक पढ़ी जाती है, लेकिन यदि नई लाइनें जोड़े जाती हैं तो कुछ भी नहीं होता है।

तलाश और टेलग के साथ मैं फ़ाइल की वर्तमान अंत स्थिति को स्टोर करने की कोशिश कर रहा हूं, ताकि जब मैं इसे फिर से खोलूं, तो मैं वहां जा सकता हूं और जो भी जोड़ा गया है उसे पढ़ सकता हूं।

मैं जानना चाहता हूं कि मेरे कोड में क्या गलत है, और यदि इस उद्देश्य के लिए एक ही फ़ाइल को बंद करना और फिर से खोलना वास्तव में आवश्यक है।

धन्यवाद।

उत्तर

12

पाश जब eof()tellg() रिटर्न -1 का सामना करना पड़ा है के रूप में सही नहीं है और तुरंत getline() करने के लिए कॉल जो वहाँ होने की जरूरत है के बाद eof() के लिए कोई चेक नहीं है। पाश को इसमें बदलें:

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

साथ ही, p के रूप में एक size_t के रूप में घोषित किया जाता है जब लौट tellg()-1p का मूल्य 4294967295 करने के लिए सेट किया जा रहा था। इसका मतलब है कि seekg() फ़ाइल के अंत से बाहर सेट किया जा रहा था। std::streamoff को p का प्रकार बदलें और कॉल की पुष्टि करने के seekg() सफल रहा था:

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

अगर यह इस उद्देश्य के लिए बंद करने और एक ही फाइल को फिर से खोलने के लिए वास्तव में आवश्यक है।

नहीं, यह आवश्यक नहीं है, लेकिन आप धारा से eof राज्य clear() की जरूरत है।

#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

अब यह ठीक से काम कर रहा है। धन्यवाद। – Pietro

+0

मैंने देखा कि यदि मैं लूप में ifstream ऑब्जेक्ट बनाता हूं तो यह काम करता है, लेकिन अगर मैं इसे बाहर बनाता हूं तो यह नहीं करता है। क्या इसे पढ़ने के लिए फ़ाइल को बंद करना और फिर से खोलना आवश्यक है? – Pietro

+0

@Pietro, आपको अगले पढ़ने के प्रयास से पहले 'ifs.clear()' को कॉल करके 'ifstream' की eof स्थिति को साफ़ करने की आवश्यकता है। मैं _think_ 'tellg()' और 'seekg()' इस दृष्टिकोण के साथ अनावश्यक होगा। – hmjd

1

इस विधि मेरे लिए ईमानदारी से काम किया है:: निम्नलिखित पोस्ट कोड का एक सही संस्करण के लिए एक विकल्प है

#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

इस कोड मेरे लिए काम करता है:

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); 
    } 
}