2012-08-01 4 views
9

내가 (tail -F가하는 일에 비슷한) 성장하는 파일에서 읽을하려고하지만, 내 코드 몇 가지 문제가 있어야합니다 : 선없이C++에서 증가하는 텍스트 파일을 읽는 방법?

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, 로그 파일을 올바르게 끝까지 읽지 만 새 줄을 추가하면 아무 일도 일어나지 않습니다.

seekg와 tellg을 사용하여 파일의 현재 끝 위치를 저장하려고합니다. 다시 열면 거기에 갈 수있어 추가 된 내용을 읽을 수 있습니다.

내 코드에서 무엇이 잘못되었는지 알고 싶습니다.이 목적으로 동일한 파일을 닫았다가 다시 열어야하는 것이 정말 필요한 경우 알려주십시오.

감사합니다.

답변

12

루프는 eof()tellg() 반환 -1가 발생하는 경우와 같이 잘못된 즉시있을 필요가 getline() 호출 후 eof()에 대한 검사가 없습니다. 변경 루프에 : -1p의 값으로 설정되는 4294967295 하였다 반환 tellg()p로서 또한

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

size_t로 선언된다. 이것은 seekg()이 파일의 끝을 넘어서 설정되었음을 의미합니다. std::streamoffp의 유형을 변경하고 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 상태를 지울 필요가 있습니다. 나는이 접근법에서'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); 
    } 
} 
관련 문제