So far, this has worked relatively nicely. However, I am having trouble in outputting to two separate files, and I'm hoping that you guys and gals can help me out. I'm reading in from a file, and outputting to two different files, based on what the input is. If anyone can advise me as to how to fix this, that would be wonderful. The strange part is that it successfully open/creates each file for the stream, and the writing works perfectly for the stream "preprocess" but not for "recordList". Issues in bold with comments. Thank you very much.

EDIT: I also have checked for recordList.fail() and its turning up false...I see no reason why this should not work!! :(

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
	string names;
	string data;
	string directory;
	string namesDirectory;
	string dataDirectory;
	size_t found;
	string currentFile=__FILE__;
	string input;
	int features=0;
	int records=0;
	char temp;
	string dataTemp;
	int debugCount=0;

	names="raw-dataset.names";
	data="raw-dataset.data";

	found=currentFile.find_last_of("\\");
	directory=currentFile.substr(0,found);
	directory+="\\data\\";

	namesDirectory=directory + names;
	dataDirectory=directory + data;

	cout << endl << "name file to be opened: " << endl << namesDirectory << endl;
	cout << "data file to be opened: " << endl << dataDirectory << endl;

	//Open the names file and count the number of features we have
	ifstream openNames;
	openNames.open(namesDirectory.c_str());
	if(openNames.is_open())
	{
		cout << "names opened successfully. " << endl;
		while(!openNames.eof())
		{
			getline(openNames,input);
				if(input[0]!='|' && !input.empty())
			{
				features++;
			}
		}
		features-=1;
		openNames.close();
	}
	else
		cout << "Unable to read file." << endl;

	cout << "There are " << features << " features."  <<endl;

	//Open the data file to simply count the number of records
	ifstream openData;
	openData.open(namesDirectory.c_str());
	if(openData.is_open())
	{
		cout << "data opened successfully for counting. " << endl;
		while(!openData.eof())
		{
			openData.get(temp);
			if(temp=='.')
				records++;
		}
		openData.close();
	}
	else
		cout << "Unable to read file for counting." << endl;

	cout << "There are " << records << " records." << endl;

	//Re-open data file to actually perform the tasks we need done
	ofstream preprocess;
	ofstream recordList;

	ifstream openData2;
	openData2.open(dataDirectory.c_str());
	preprocess.open ("data//dataset.dat");
	recordList.open ("data//answers.dat");

	if(openData2.is_open() && preprocess.is_open() && recordList.is_open())
	{
		cout << "data files opened and created successfully for analysis. " << endl;
	[B]	preprocess << records << " " << features << "\n"; //Writes successfully
		recordList << records << "\n";//Doesn't write successfully[/B]
		while(!openData2.eof())
		{
			if(openData2.peek()=='n')
			{
				recordList << "nonad" << "\n";
				getline(openData2,dataTemp,'.');
				preprocess << "\n";
                                //This doesn't write successfully, but it goes to the correct spot in the code


			}
			else if(openData2.peek()=='a')
			{
				recordList << "ad" << "\n";
				getline(openData2,dataTemp,'.');
				preprocess << "\n";
//This doesn't write successfully, but it goes to the correct spot in the code
			}
			else
			{
				getline(openData2,dataTemp,',');
				preprocess << dataTemp << " ";
                                //Works just fine

			}
			debugCount++;
			cout << debugCount << " of " << records << endl;
		}

		openData2.close();
		preprocess.close();
		recordList.close();
	}
	else
		cout << "Unable to read/write files for analysis." << endl;

	return 0;
}
Clinton Portis commented: A thorough and very well stated question w/ suspected problem areas already highlighted. +5

Recommended Answers

All 7 Replies

Your code looked pretty good, and just glancing over your code, I was kinda stumpted at first, but I think I might have a possible solution for ye'...

I believe that your .dat files contain a bunch of stuff. You read in the files succesfully without incident.

I believe the problem occurs when you open the files for writing using your ofstream objects; you open the files in the default mode (ios::out) which is fine... but I do believe the file 'put' pointer is set to the beginning of the files by default (this is not specifically mentioned in the documentation for ofstream's open() function... this conclusion is based soley on my experience.)

My suggestion is to open your files with your 'ofstream' object using the ios::ate flag to ensure that you are not attempting to over-write existing file data (which I think can lead to unpredictable performance):

//Feel free to use the bitwise OR operator to combine flags to meet your needs
preprocess.open ("data//dataset.dat", ios::out|ios::ate);
recordList.open ("data//answers.dat", ios::out|ios::ate);

Now you should be able to append data 'at the end' of your files.

The .dat files are simply a list of records, in the format "0,0,0, ect, ." It's okay for the operators to overwrite them, its just that the actual WRITE operation doesn't take place, even if the files don't exist in the first place. That's what I don't understand here...it makes no sense to me whatsoever. :(

Just out of curiosity, have you tried performing the file operations while opened in binary mode?

//sometimes when I can't figure stuff out, I'll see if the same behavior
//exists in binary mode:
preprocess.open ("data//dataset.dat", ios::out|ios::binary);
recordList.open ("data//answers.dat", ios::out|ios::binary);

Tried ios::binary and I tried separating them entirely, even though that would be horribly inefficient...still doesn't work.

Solved:
Turns out that file streams and "\n" do not play nicely together. I instead switched all of the "\n" to endl, and it's working fine now. Picky, picky. If anyone can tell me why this happens, I would really appreciate it so that I can better understand the little things. Thanks for your help!

Sorry, double post.

Out of curiosity, I looked up the documentation for endl and might have some sort of answer for ye':

endl

manipulator function
<ostream>

ostream& endl ( ostream& os );

Insert newline and flush
Inserts a new-line character.
Additionally, for buffered streams, endl flushes the buffer (i.e. writes all unwritten characters in the buffer to the output sequence, see ostream::flush).

It seems to me the ability to flush the output buffer may have a beneficial affect as compared to it's '\n' newline ascii counterpart, which to my knowledge does not flush the buffer.

Out of curiosity, I looked up the documentation for endl and might have some sort of answer for ye':

It seems to me the ability to flush the output buffer may have a beneficial affect as compared to it's '\n' newline ascii counterpart, which to my knowledge does not flush the buffer.

Ahhh...that makes sense. So, it was leaving residue behind in the buffer that was causing it to output blank space instead of what it should have. Thank you very much for all your help. I learned something new today!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.