[C++] Opening multiple files, weird bug

Started by
8 comments, last by Zahlman 18 years, 7 months ago
Well I've created a program to open a list of files that are just different by an ID number, ie. 000015.txt 000017.txt... I'm using the fstream library to read the files, but I'm getting an issue. When it's running through the loop, it will open the first file in the series, but it won't open anymore after that. Say I told it to start at ID 15 and read all the files, it will open 15 read it, close it, and not open the rest of them. Here's the code if you're intersted:
void main()
{
	ofstream out;
	ifstream in;
	std::string date, time, meridian, email, file;
	
	char *i2a = new char[8];
	short unsigned int endnum=0;
	short unsigned int startnum=0;

	//Get values
	cout << "Enter starting ID value: ";
	cin >> startnum;
	cout << endl << "Enter ending ID value: ";
	cin >> endnum;

	system("cls");

	cout << "Ready to open!\n";

	//Open write stream
	out.open("Campaign_Opens.txt");
	out << "id,date,email\n"; //Setup header

	//Process
	for(int i = startnum; i <= endnum; i++)
	{
		//Appropriately create filename to open
		if(i > -1 && i < 10)
		{
			file = ".\\CampaignID00000";
			itoa(i, i2a, 10);
			file += i2a;
			file += "-OpenedEmail.txt";
		}
		else if(i > 9 && i < 100)
		{
			file = ".\\CampaignID0000";
			itoa(i, i2a, 10);
			file += i2a;
			file += "-OpenedEmail.txt";
		}
		else if(i > 99 && i < 1000)
		{
			file = ".\\CampaignID000";
			itoa(i, i2a, 10);
			file += i2a;
			file += "-OpenedEmail.txt";
		}
		else if(i > 999 && i < 10000)
		{
			file = ".\\CampaignID00";
			itoa(i, i2a, 10);
			file += i2a;
			file += "-OpenedEmail.txt";
		}
		else
		{
			file = ".\\CampaignID0";
			itoa(i, i2a, 10);
			file += i2a;
			file += "-OpenedEmail.txt";
		}
		
		//Open file for reading
		in.open( file.c_str() );

		//If the file is valid and opened
		if(in.is_open())
		{
			//Read file data
			while(!in.eof())
			{
				//Get data
				in >> date >> time >> meridian >> email;

				//Write new line out to buffer
				out << i2a << "," << date << " " << time << " " << meridian << "," << email << endl;
			 }

			//Clean up
			in.close();
			file = "";
			date = "";
			time = "";
			meridian = "";
			email = "";

			for(int ii=0; ii < 8; ii++)
			{
				i2a[ii] = NULL;
			}
		}
	}

	//Clean up
	out.close();
	delete [] i2a;
}
I'm not quite sure why it's doing this. While I debug it, it shows the proper filenames to open, it's just not opening them. Any reason why? Thanks!
-Conrad
Advertisement
Well atleast:
out << "id,date,email\n"; //Setup header

..should be:
out << id << date << email << "\n"; //Setup header
..if you want to output the values instead of just "email" etc.

I couldnt find the problem why it doesnt open the files, I'm ust too tired ;)




No the header is right, I'm creating a comma delimited format for import into your MSSQL DB.
-Conrad
Anyone?
-Conrad
I believe you need to .reset() the file object each time in addition to .close()ing it; otherwise, the ifstream already has its eofbit set when you open the second file.

Although I personally would avoid the problem by using an ifstream local to the loop:

for(int i = startnum; i <= endnum; i++) {  // Appropriately create filename to open  // By the way, itoa() is awful - non-standard and ancient. I'll redo  // this part using modern tools:  stringstream filenameBuilder("./CampaignID");  // by the way, use forward slashes in your file names, even on platforms  // where that isn't the filename separator - see here:  // http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.16  filenameBuilder << setfill('0') << setw(6) << i << "-OpenedEmail.txt";  // Now we can open the file:  ifstream in(filenameBuilder.str().c_str());  // Yes, those three lines really replace all of your filename construction  // code, and also create a new ifstream object each time through the loop  // with the appropriate filename. :)    // While possible to read a line. If the file couldn't be opened,   // this will fail right away and do nothing, just as it did before.  // This also fixes the bug whereby .eof() doesn't return true until *after  // a failed read*, which would add a duplicate of the last line to your output  // (assuming I'm thinking clearly).    while(in >> date >> time >> meridian >> email) {    out << i << "," << date << " " << time << " " << meridian         << "," << email << endl;  } // 'i2a' previously just held a string representation of the number, and    // outputting a number to a stream with operator<< works just fine, so I    // just substituted the actual number there.}// No cleanup is needed: this ends the scope so the current ifstream will have// its destructor called (closing the file automatically), and a new one is// constructed next time through. None of the strings really need to be// re-initialized because we'll only ever output them when we were successful// in reading values into them (this holds for the original code too).// The i2a buffer didn't need to be cleaned up before, either, but now it// isn't even present. I'd just like to comment that setting individual // *characters* to 'NULL', while it may work, is misleading: C++ defines// NULL as 0, which happens to be the necessary value for null termination,// but it's really meant to indicate a null *pointer*. For chars, use '\0'// instead.


This feels much more C++-idiomatic to me too, making use of the powerful RAII paradigm.
reset() isn't a member function for the stream classes. I already tried looking for something to reset it each time.
-Conrad
I think Zahlman meant clear().
Quote:Original post by Zahlman
I believe you need to .reset() the file object each time...

.clear(). Clears a streams failbit.
try making the ifstream in object into a scope variable, and hope the destructor cleans up whatever the hell is wrong with it. change: in.open( file.c_str() ) to ifstream in( file.c_str() )

Just a suggestion, FYI, this may have something to do with the crappy default STL implementation of Visual C++ 6.0 compiler (if thats what you're using)

EDIT: might also want to try a call to in.flush() just before closing the file object.
"I am a donut! Ask not how many tris/batch, but rather how many batches/frame!" -- Matthias Wloka & Richard Huddy, (GDC, DirectX 9 Performance)

http://www.silvermace.com/ -- My personal website
Right. What would I do without you guys? :)

This topic is closed to new replies.

Advertisement