2 questions about files

Jan 30, 2010 at 12:42am
For some reason when I use the following code, all the Person's in my file get NULL'ed up to the one being written. Any ideas what's wrong with the following:


1
2
3
4
	dFile.open("persons.bin", ios::out, ios::binary);
	dFile.seekp((sizeof(Person) * id), ios::beg);
	dFile.write((char *) &p, sizeof(Person));
	dFile.close();


Second question is, is there a way to store the current cursor position into an integer?
Jan 30, 2010 at 2:28am
What is the p object? Does it point to something valid? What is the Person type? Is it a POD type? Please show a complete program that demonstrates the problem. There is no way to tell what is wrong looking only at that small chunk of code.

tellp tells where the current position is. It is easy to story the return value to a variable. It is a common technique for determining a file size. Seek to the end and then use tellp to indicate how many bytes are within the file.
Jan 30, 2010 at 2:30am
1. By default, files are truncated when opened. To prevent this, open with the flag std::ios::app (IINM). In your case, that would be std::ios::binary|std::ios::app.
1. What kempofighter said.
2. std::fstream::tellp() and std::fstream::tellg(). One returns the writing position, and the other the reading position.
Last edited on Jan 30, 2010 at 2:31am
Jan 30, 2010 at 2:43am
A Person

1
2
3
4
5
class Person {
public:
char fName[100], lName[100], addy[200], gend;
int age;
};


I cannot use append, because I need to overwrite a certain Person in the file not add to the end. The file contains x number of records each one is located by multiplying sizeof(Person) by the record of the person in the file (records are sequential from 0).

My file is writing and reading the records fine but when I try to modify an existing record it doesn't delete the records it just NULLS everything until the point to be written. It's very frustrating...I've tried everything I can think of.
Jan 30, 2010 at 2:53am
In that case, I was right. Without std::ios::app, the file is truncated. You're not forced to add something at the end. The flag just means "don't blank the file when I open it".
Jan 30, 2010 at 2:58am
I did as you said and changed it to this:

1
2
3
4
	mFile.open("persons.bin", ios::binary | ios::out | ios::app);
	mFile.seekp((sizeof(Person) * id), ios::beg);
	mFile.write((char *) &p, sizeof(Person));
	mFile.close();


At least it's not NULL'ing everything but instead it still adds the modified Person to the end of the file instead of where the pointer is. Any ideas???
Jan 30, 2010 at 3:06am
 
mFile.open("persons.bin", ios::out | ios::binary);

You are still playing with fire by reading/writing a class directly to file.
Jan 30, 2010 at 3:10am
no luck, still NULL'ing everything above the one being edited. I know I'm playing with fire but this is the way our teacher has asked us to do this assignment stating he'll teach us a better method later. I've spent a lot of time debugging this issue and I'm at a loss hoping you guys will have some insight. I really appreciate the help thus far.
Jan 30, 2010 at 3:16am
update: not only is it NULL'ing everyting, it's still putting the edited person at the end of the file...
Jan 30, 2010 at 3:21am
What is the value of id? I can't stress enough how important it is to provide a complete program. Everyone is taking Scientific Wild Ass Guesses (SWAGs) as to what you might be doing. Sometimes SWAGs are pretty close to being correct and sometimes they aren't. Just put together a simple main and show as something that we can compile and try out. Unfortunately I don't think that you can attach a file but seeing something more complete would be very helpful.
Jan 30, 2010 at 3:23am
You could try storing sizeof(Person) into a variable and see if the value makes sense. I have never seen file io done like that before but I can't imagine what the problem is without a complete example.
Last edited on Jan 30, 2010 at 3:25am
Jan 30, 2010 at 3:36am
OK here's my entire code, it's not completely implemented yet but it compiles and will let you try and find the bug.

person.h
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
#ifndef HEAD
#define HEAD

#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;

class Person //ID is stored by position in file
{
public:
	char fName[100], lName[100], addy[200], gend;
	int age;
};

void CreateFile();

void AddPerson();

void PrintDB();

void DeletePerson();

void ModifyPerson();


#endif; 


person.cpp:
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
#include "person.h"

void CreateFile()
{
	fstream cFile;
	cFile.open("persons.bin", ios::in, ios::binary);
	if (cFile.fail())
	{
		cFile.open("persons.bin", ios::out, ios::binary);
		cout << "The file was created successfully" << endl << endl;
	}
	else
	{
		cout << "The database file already exists" << endl << endl;
	}
}

void AddPerson()
{
	fstream wFile;
	Person p;
	//Get info
	cout << "Enter the first name: ";
	cin >> p.fName;
	cout << "Enter the last name: ";
	cin >> p.lName;
	cout << "Enter the age: ";
	cin >> p.age;
	cout << "Enter gender (M or F): ";
	cin >> p.gend;
	cout << "Enter address: ";
	cin.ignore();
	cin.getline(p.addy, 199);

	wFile.open("persons.bin", ios::app, ios::binary);
	wFile.seekp(0, ios::end);
	wFile.write((char *) &p, (sizeof(Person)));
	wFile.close();
	cout << "Person was added successfully" << endl << endl;
}

void PrintDB() //INCOMPLETE
{
	fstream pFile;
	Person p;
	int k = 0;

	pFile.open("persons.bin", ios::in, ios::binary);
	while (!pFile.eof())
	{
		pFile.seekg((sizeof(Person)*k), ios::beg);
		pFile.read((char *) &p, sizeof(Person));
		cout << k << ", " << p.fName << ", " << p.lName << ", " << p.gend << ", " << p.age  << ", " << p.addy << endl;
		k++;
	}
	pFile.close();
}

void DeletePerson()  //INCOMPLETE
{
	Person p;
	int id;
	fstream dFile;

	strcpy(p.fName, "{EMPTY}");
	strcpy(p.lName, "{EMPTY}");
	strcpy(p.addy, "{EMPTY}");
	p.age = 0;
	p.gend = '?';

	cout << "Enter ID of person to delete: ";
	cin >> id;
	
	dFile.open("persons.bin", ios::out, ios::binary);
	dFile.seekp((sizeof(Person) * id), ios::beg);
	dFile.write((char *) &p, sizeof(Person));
	dFile.close();
	cout << "The person was deleted successfully" << endl << endl;
}

void ModifyPerson()  //INCOMPLETE
{
	Person p;
	int id;
	fstream mFile;

	cout << "Enter ID of person to modify: ";
	cin >> id;
	cout << "Enter the first name: ";
	cin >> p.fName;
	cout << "Enter the last name: ";
	cin >> p.lName;
	cout << "Enter the age: ";
	cin >> p.age;
	cout << "Enter gender (M or F): ";
	cin >> p.gend;
	cout << "Enter address: ";
	cin.ignore();
	cin.getline(p.addy, 199);
	
	mFile.open("persons.bin", ios::out | ios::binary);
	mFile.seekp((sizeof(Person) * id), ios::beg);
	mFile.write((char *) &p, sizeof(Person));
	mFile.close();
}


main program:
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
#include "person.h"

int main()
{
	char choice = '\0';

	while (choice != 'Q')
	{
		//show menu
		cout << "MENU:    (C)reate a new empty file (if one doesn't already exist)" << endl;
		cout << "         (A)dd a person to end of database" << endl;
		cout << "         (D)elete a person by ID" << endl;
		cout << "         (M)odify a person by ID" << endl;
		cout << "         (P)rint database info" << endl;
		cout << "         (Q)uit program" << endl;
		cout << ">:";
		cin >> choice;

		switch (choice)
		{
		case 'c':
		case 'C':
			CreateFile();
			break;
		case 'a':
		case 'A':
			AddPerson();
			break;
		case 'd':
		case 'D':
			DeletePerson();
			break;
		case 'm':
		case 'M':
			ModifyPerson();
			break;
		case 'p':
		case 'P':
			PrintDB();
			break;
		case 'q':
		case 'Q':
			choice = 'Q';
			break;
		default:
			cout << "You have entered an invalid choice" << endl << endl;
			break;
		}
	}

	return 0;
}
Jan 30, 2010 at 3:40am
You need to press C first before anything else to create the binary file otherwise the other functions will not work.
Jan 31, 2010 at 1:39am
This is why I tried to avoid posting all my code because it scares ppl off and I get no help. Either way I finally figured out the problem, The line needed ios::in flag also.
Topic archived. No new replies allowed.