It's temping to use the stream extraction operator, >> , to read from files, but I almost never find it to be a good idea, for reasons like you're finding.
The most robust way to read this kind of data is to use getline , see the example here . This way you can get a line from the file and discard it if it has zero length (or, more correctly, if it's empty). The downside to this is that you have to split the line into individual tokens manually. For your data, this isn't too hard. If you read the line into a std::string then you can use a std::stringstream to process the data in a similar way to the way you're currently doing it. Here's a simple example that does this:
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>
struct LineData
{
int x;
int y;
int z;
friend std::ostream& operator<<( std::ostream& right, const LineData& data )
{
right << "(" << data.x << ", " << data.y << ", " << data.z << ")";
return right;
}
};
int main()
{
std::ifstream file( "test.txt", std::ios::in );
if ( ! file.is_open() )
return 1;
std::vector< LineData > vLineData;
while ( ! file.fail() )
{
std::string lineFromFile;
getline( file, lineFromFile ); // Get a line from the file and store it in a string
if ( lineFromFile.empty() )
continue; // Skip blank lines
std::stringstream ss( lineFromFile ); // Make a stringstream from the line from the file
LineData temp;
ss >> temp.x >> temp.y >> temp.z; // Extract the tokens on the line from the string
if ( ! ss.fail() ) // Don't add lines that didn't read properly
vLineData.push_back( temp );
}
// Print out all the line data that we read, to check that we got all the lines properly
std::copy( vLineData.begin(), vLineData.end(), std::ostream_iterator< LineData >( std::cout, "\n" ) );
return 0;
}