Friday, September 11, 2009

C++: if file line length exceeds array (buffer) length

Suppose we have implemented the following scenario:

  1. // read input file line by line  
  2. // allocate 256 characters for each line  
  3.   
  4. ifstream input_file("some_file.txt");  
  5. const int BUF_SIZE=256;  
  6. char buf[BUF_SIZE];  
  7. string s, strCurString;  
  8.   
  9. if (!input_file.is_open())  
  10. {  
  11.    cerr << "File some_file.txt coudl not be open!" << endl;  
  12.    getch();  
  13.    exit(EXIT_FAILURE);  
  14. }  
  15.   
  16. while(!input_file.eof()) {  
  17.    input_file.getline(buf, BUF_SIZE);  
  18.    strCurString = buf;  
  19.    s += strCurString;  
  20. }  
  21.   
  22. cout << "File contents: " << endl << s << endl;  


But what if the current file length exceeds BUF_SIZE? Well, in this case the while loop will never end, becoming an infinite loop. Why? Simply, because in the input file stream object a special bit (failbit) will be set, saying that the last getline() operation has failed (in this case not due to the end of a file, but due to the buffer length exceeding). In this case all subsequent calls to getline() will fail to read anything (can be seen by calling input_file.gcount(), which constantly returns 0 (zero) after the last getline() call that led to setting a failbit).


To overcome this, we can use a trick found here:

  1. // read input file line by line  
  2. // allocate 256 characters for each line  
  3.   
  4. ifstream input_file("some_file.txt");  
  5. const int BUF_SIZE=256;  
  6. char buf[BUF_SIZE];  
  7. string s, strCurString;  
  8.   
  9. if (!input_file.is_open())  
  10. {  
  11.    cerr << "File some_file.txt coudl not be open!" << endl;  
  12.    getch();  
  13.    exit(EXIT_FAILURE);  
  14. }  
  15.   
  16. while(!input_file.eof()) {  
  17.    input_file.getline(buf, BUF_SIZE);  
  18.   
  19.    // remember about failbit when amount of  
  20.    // characters in the current line is  
  21.    // more than BUF_SIZE  
  22.    if (input_file.fail() && !input_file.eof())  
  23.        // clear up the failbit and   
  24.        // continue reading the input file  
  25.       input_file.clear();  
  26.    strCurString = buf;  
  27.    s += strCurString;  
  28. }  
  29.   
  30. cout << "File contents: " << endl << s << endl;  

No comments: