fstream stops reading in new data

Hi all.
Having issues with this basic database program I'm writing.
The database consists of two files, one is sorted records, and the other is unsorted ones, ones that have just been created and have yet to be added to the sorted side.

The program merges the two files once the overflow hits a certain size, or once the database is asked to close down.

Everything works great until the end of the merge, at which point fstream just refuses to read in any new data. I've tried closing and reopening the file, creating new variable objects, using a new fstream object. Nothing works or helps.

If you've got any suggestions, please let me know. I've been trying to fix this one little error for hours and I'm out of ideas.

I've tried to comment it to make it easier to read, but for shortcuts sake, the line where its breaking is line 133.

I've also put it into a pastebin, if anyone prefers that.
http://pastebin.com/FFvJFMxZ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  bool mergeOfl(ifstream &Din, string &Id, int &Experience, string &Married, float &Wage, string &Industry)
{

	string ipath = FILENAME + "input.txt";
	string path = FILENAME + "overflow.txt";
	string tpath = FILENAME + "temp.txt";

	string Id2 = "ID";
	int Experience2 = -1;
	string Married2 = "UNKNOWN";
	float Wage2 = -1.0;
	string Industry2 = "INDUSTRY";

	int temp;
	string msid;

	bool found = true;

	ofstream outfile(tpath.c_str());
	outfile.close();
	ifstream Din2(path.c_str());

	NUM_RECORDS += OFL_RECORDS;

	cout << "** Merging database subsections." << endl;

	headLine(tpath);


	//get the last record ID of the sorted section, ie the largest
	Din.seekg(-69, ios::end);
	Din >> msid;
	Din.seekg(71, ios::beg);
	Din2.seekg(0, ios::beg);

	cout << "** Largest sorted ID is: " << msid << endl;

	temp = atoi(msid.c_str());

	//cycle through the IDs from 1 to largest ID
	//if it doesnt exist in the sorted section, check the unsorted section
	for(int x = 1; x <= temp; x++)
	{
		//if we found the last ID, the sorted section can check the next line
		if(found == true)
		{
			Din >> Id >> Experience >> Married >> Wage >> Industry;
			//check sorted section
			if(atoi(Id.c_str()) == x)
			{
				if(Experience != -1)
				{
					appLine(Id, Experience, Married, Wage, Industry, tpath);
				}
				else
				{
					NUM_RECORDS--;
				}
				found = true;
			}
			//check unsorted section
			else
			{
				stringstream ss;
				ss << x;
				string tempid = modID(ss.str());


				if(linearSearch(Din2, tempid, Experience2, Married2, Wage2, Industry2) == true)
				{
					appLine(tempid, Experience2, Married2, Wage2, Industry2, tpath);
					//need to make sure we dont try to merge this record again
					updateRecord(Din2, tempid, Experience2, Married2, Wage2, Industry2, 1, "-1");
				}
					found = false;

			}
		}
		//if we didnt find the last ID, we need to stay on the current line in the sorted section
		else
		{
			//check sorted section
			if(atoi(Id.c_str()) == x)
			{
				if(Experience != -1)
				{
					appLine(Id, Experience, Married, Wage, Industry, tpath);
				}
				else
				{
					NUM_RECORDS--;
				}
				found = true;
			}
			//check unsorted section
			else
			{
				stringstream ss;
				ss << x;
				string tempid = modID(ss.str());


				if(linearSearch(Din2, tempid, Experience2, Married2, Wage2, Industry2) == true)
				{
					appLine(tempid, Experience2, Married2, Wage2, Industry2, tpath);
					//need to make sure we dont try to merge this record again
					updateRecord(Din2, tempid, Experience2, Married2, Wage2, Industry2, 1, "-1");
				}

				found = false;
			}
		}

	}

	Din.close();
	Din2.close();
	Din2.open(path.c_str());

	string stemp;
	//int count = OFL_RECORDS - 1;

	//now we need to cycle through the rest of the unsorted section
	//and merge any unused records, starting with the smallest
	for(int x = 0; x < OFL_RECORDS; x++)
	{
		Din2.seekg(x * RECORD_SIZE, ios::beg);
		//cout << Din2.tellg() << endl;

		//this is where it breaks
		//din2 fails to pull in any new data, so ID is still the
		//last id from the sorted section
		Din2 >> Id >> Experience >> Married >> Wage >> Industry;
		if(Experience == -1)
		{
			continue;
		}
		else
		{
			//compare selected ID to every other ID...
			Din2.seekg(0, ios::beg);
			for(int y = 0; y < OFL_RECORDS; y++)
			{
				//except for our own
				if(y != x)
				{
					Din2 >> Id2 >> Experience2 >> Married2 >> Wage2 >> Industry2;
					//if the record has been deleted or already used, skip it
					if(Experience2 == -1)
					{
						continue;
					}
					//elsewise compare it and choose the smaller ID record
					else
					{
						if(atoi(Id2.c_str()) < atoi(Id.c_str()) && Experience2 != -1)
						{
							Id = Id2;
							Experience = Experience2;
							Married = Married2;
							Wage = Wage2;
							Industry = Industry2;
						}
					}


					appLine(Id, Experience, Married, Wage, Industry, tpath);
					//make sure we dont use the chosen record again
					updateRecord(Din, Id, Experience, Married, Wage, Industry, 1, "-1");
				}
				//skipping our own ID
				else
				{
					Din2 >> Id2 >> Experience2 >> Married2 >> Wage2 >> Industry2;
				}
			}
		}
	}

	Din2.close();

	//remove(ipath.c_str());
	//remove(path.c_str());
	//rename(tpath.c_str(), ipath.c_str());

	//reset the number of unsorted records
	OFL_RECORDS = 0;

	return true;

}
I haven't looked too closely, but in general: Don't use seekg or seekp in files that you have not opened as binary files. You should also not use formatted input extraction for binary files (so that needs to change if you actually do open them as binary files.)
It's formatted input extraction because I ensure every line is the same length. I probably should have mentioned that.

Every field in the record is given a set field width, and Im keeping everything in UNIX formatting.
Last edited on
Selver wrote:
It's formatted input extraction because I ensure every line is the same length.
That's not relevant. You can't seek in a file stream opened as formatted I/O because it is undefined behavior. If you don't need automatic EOL conversion, use unformatted I/O.
It's formatted input extraction because I ensure every line is the same length. I probably should have mentioned that.

Kind of irrelevant to what I'm saying.

Either use binary mode with read/write operations or use text mode with formatted input extraction and don't seekp/seekg to positions not supplied by tellp/tellg. Unless something has changed that I'm not aware of, what you are doing results in undefined behavior, regardless of the format of your file.
Alright, I guess I'm going to have to figure out how to make those modifications, since up to this point none of my seekg uses have caused any issues.

Heck, even some of the code provided by the professor is using seekg, so that's why I started off with that.
Last edited on
You can still use seekg but you should open the stream with the std::ios::bin flag.
Alright, I'll try that, thanks.
Topic archived. No new replies allowed.