how to output a char array as binary to a file

I have 2 programs. One that prompts the user for 5 lines of a limerick poem and one that displays the limerick back to you. Well, it is suppose to anyways. I'm not sure where the problem lies. It creates a Limerick.dat file and when I open it I can see some of the words and the rest is, I assume, binary. When I try to retrieve it however I just get blocks of white lines.

Any help would be appreciated. Thanks for your time.


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
//prompts user for 5 lines of a limerick poem

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

template<typename T>
ostream& binary_write(std ostream& stream, const T& value)
{
	return stream.write(reinterpret_cast<const char*>(&value), sizeof(T));
}

int main()
{
	char tempChar[100];
	const char* FILENAME = "C:\\Users\\Admin\\Limerick.dat";
	ofstream writingFile(FILENAME, ios::out | ios::binary);
	
	//creates fixed length dat file
	for (int x = 0; x < 6; ++x)
		binary_write(cout, tempChar)


	if (!writingFile.good())
		cout << "File could not be opened for writing" <<
		endl;
	else
	{
		cout << "You will be prompted for 5 lines of a Limerick poem." << endl << endl;

		for (int x = 0; x < 6; ++x)
		{
			
			cout << "Enter line " << x << ": ";
			cin.getline(tempChar);
			writingFile.seekp((x - 1) * sizeof(tempChar));
			binary_write(cout, tempChar);
			
		}

	}

	//closes file
	writingFile.close();

	system("Pause");
	return 0;
}



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
//displays limerick

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


int main()
{

	
	const char* FILENAME = "C:\\Users\\Admin\\Limerick.dat";
	ifstream readingFile(FILENAME, ios::in | ios::binary);
	

	if (!readingFile.good())
		cout << "File could not be opened for reading" <<
		endl;
	else
	{
		for (int x = 0; x < 6; ++x)
		{
			char tempChar[100];
			readingFile.seekg((x - 1) * sizeof(tempChar));
			readingFile.read(reinterpret_cast <char*>(&tempChar), sizeof(tempChar));
			cout << x << ":  " << tempChar << endl;
			
		}

	}

	//closes file
	readingFile.close();

	system("Pause");
	return 0;
}
What compiler are you using?
visual studio 2013
That's good, but that code shouldn't even compile so I don't know how you're testing it. What are you trying to accomplish with this code? I know you want to read in a limmeric, save it, and read it out again, but what you have here ( other than being uncompilable ) is way more complex than it needs to be. Are you trying to learn new things, or do you just not know what you're doing?
A bit of both I guess lol. I am still very new to programming and I am trying to learn how to take a literal string and store it, in binary, in a fixed length file that I created. The seekg() and seekp() functions are included just so I can practice using them. If there is a better, more efficient, way to do this please point me in the right direction. I could easily do this with text but I know how that is done already. I'm trying to understand how binary strings are read to and from a file to advance my knowledge of programming.
Alright, lets start with the first one then.


You never use anything from iomanip and there's no reason to, so remove it.

You're using namespace std; so std ostream in line 9 should just be ostream. If you weren't using namespace std;, it would be std::ostream.

You forgot the semicolon at the end of line 22. You should also be writing to writingFile, not cout. You made that same mistake on line 38.

Change line 32 to for ( int x = 1; x < 6; ++x ). You're off by one. It's a fairly common mistake.

cin.getline has to be passed two things: the location to store the data, and the amount of data to store. You have the first, the second should be the length of tempChar ( 100 ).

There's no reason to seekp within the loop. You could seekp(0) before the loop and it would work fine, but you said you wanted to try using these functions and your code isn't wrong so there's no need to remove it.

I have to go so I'll do this quick. Change binary_write to:
1
2
3
4
5
template<typename T>
ostream & binary_write ( ostream & stream, const T & value, int length )
{
	return stream.write ( value, sizeof ( T ) * length );
}

and change the two lines that call it to binary_write ( writingFile, tempChar, 100 );.

That should be everything. I'll be back tomorrow.
Hey, thanks for the feedback. I really appreciate it. Those changes make a lot of sense. I have been trying to figure this one out for a while now. I revised my code as follows:

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
#include<iostream>
#include<fstream>

using namespace std;

template<typename T>
ostream & binary_write(ostream & stream, const T & value, int length)
{
	return stream.write(value, sizeof(T) * length);
}

int main()
{
	char tempChar[100];
	const char* FILENAME = "C:\\Users\\Admin\\Limerick.dat";
	ofstream writingFile(FILENAME, ios::out | ios::binary);
	
	//creates fixed length dat file
	for (int x = 0; x < 6; ++x)
		binary_write(writingFile, tempChar, 100);


	if (!writingFile.good())
		cout << "File could not be opened for writing" <<
		endl;
	else
	{

		cout << "You will be prompted for 5 lines of a Limerick poem." << endl << endl;
		writingFile.seekp(0);

		for (int x = 1; x < 6; ++x)
		{
			
			cout << "Enter line " << x << ": ";
			cin.getline(tempChar);
			binary_write(writingFile, tempChar, 100);
			
		}

	}

	//closes file
	writingFile.close();

	system("Pause");
	return 0;
}


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
#include<iostream>
#include<fstream>
using namespace std;

template<typename T>
istream & binary_read(istream & stream, T & value, int length)
{
	return stream.read(value, sizeof(T) * length);
}

int main()
{

	
	const char* FILENAME = "C:\\Users\\Admin\\Limerick.dat";
	ifstream readingFile(FILENAME, ios::in | ios::binary);
	

	if (!readingFile.good())
		cout << "File could not be opened for reading" <<
		endl;
	else
	{
		readingFile.seekg(0);

		for (int x = 1; x < 6; ++x)
		{
			char tempChar[100];
			
			binary_read(readingFile, tempChar, 100);
			cout << x << ":  " << tempChar << endl;
			readingFile.seekg(x * (sizeof(tempChar) * 100));
			
		}
	
		//closes file
		readingFile.close();

	}

	

	system("Pause");

	return 0;
}


the writing file seems to work but I get an error when I try to read it. It says access violation. Is the logic off on my seekg() function?
Yes. It was the thing I didn't have time to explain last night. I had you change your binary_write function because when you use sizeof() it returns the size of the object you give it. When you pass an array to a function, it doesn't pass the entire array. It only passes a pointer to the first item in the array. So when you use sizeof() on tempChar, it returns the size of the pointer, not the size of the entire array. In your second program though, you are using sizeof() on the entire array because it's a local variable; it's not being passed as a pointer. So readingFile.seekg(x*sizeof(tempChar)); would be correct on line 32.
oh, thanks. It would have taken me a while to figure that out. Still getting "Access violation reading location 0x0000004B" when using the second program. I have tried different file paths using public directories and am running visual studio as admin. the reading program doesn't produce any output just the exception. does this program work for you?
I don't know why I didn't realize this before, but sizeof(T) * length is wrong. As I said before, sizeof(T) when T is a pointer will give you the size of a pointer on your system (4 for 32bit programs). The size of a char is 1. So instead of stream.write ( value, sizeof(T) * length );, it should be stream.write ( value, length );, and length has the be the number of bytes you want to print out (calculated before entering the function).


Also,
1
2
for (int x = 0; x < 6; ++x)
    binary_write(writingFile, tempChar, 100);

should be moved inside the else statement, and the 6 should be a 5 (or change the 0 to a 1).


Line 32 fails on the last loop, but it doesn't matter in this case.
That's what the problem was. Thanks so much for your help. It is working after those changes.
Topic archived. No new replies allowed.