Writing Struct to File doesn't work - what am I doing wrong?

P

paul.anderson

This code doesn't work - the first retrieval of t2 returns valid data,
the subsequent do not. Please help!!!

int main(int argc, char* argc){
struct Test{
int i;
int j;
intk;
int l;
}

Test Test1;
Test1.i = 99;
Test1.j = 777;
Test1.k = 12345;
Test1.l = 876;

fstream fout;
fout.open("test.txt", ios::eek:ut);

for (int i=0; i<10; i++)
fout.write(reinterpret_cast<char*>(&Test1), sizeof(Test));
fout.close();

fstream fin;
fin.open(test.txt", ios::in);
for(int i=0; i<10; i++){
char c[sizeof(Test)];
fin.get(c, sizeof(Test));
Test t2;

// === THIS COPY OF t2 CONTAINS CORRECT DATA FIRST TIME BUT NOT
SUBSEQUENT
// TIMES!!!!!!!!!
memcpy(&t2, c, sizeof(Test));

}




}
 
L

Larry Smith

This code doesn't work - the first retrieval of t2 returns valid data,
the subsequent do not. Please help!!!

#include said:
int main(int argc, char* argc){
struct Test{
int i;
int j;
intk;
int l;
}

missing trailing semi-colon above.
Test Test1;
Test1.i = 99;
Test1.j = 777;
Test1.k = 12345;
Test1.l = 876;

fstream fout;
fout.open("test.txt", ios::eek:ut);

// you must be using MS Windows... to read/write binary
// data you have to open the file in binary mode.
fout.open("text.txt", ios_base::eek:ut | ios_base::binary );
for (int i=0; i<10; i++)
fout.write(reinterpret_cast<char*>(&Test1), sizeof(Test));
fout.close();

fstream fin;
fin.open(test.txt", ios::in);

fin.open("test.txt", ios_base::in | ios_base::binary );

for (int x = 0; x < i; ++x )
{
Test t2;
for(int i=0; i<10; i++){
char c[sizeof(Test)];
fin.get(c, sizeof(Test));
Test t2;

// === THIS COPY OF t2 CONTAINS CORRECT DATA FIRST TIME BUT NOT
SUBSEQUENT
// TIMES!!!!!!!!!
memcpy(&t2, c, sizeof(Test));

}




}
 
S

Salt_Peter

This code doesn't work - the first retrieval of t2 returns valid data,
the subsequent do not. Please help!!!

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <iterator>

struct Test {
int i, j, k, l;
};
int main(int argc, char* argc){struct Test {
int i, j, k, l;
};
struct Test{
int i;
int j;
intk;
int l;
}

Types need a semicolon and are not placed in main()
Test Test1;
Test1.i = 99;
Test1.j = 777;
Test1.k = 12345;
Test1.l = 876;

Either an aggregate list or Test ctor would be handy.

Test test = {99, 777, 12345, 876};
fstream fout;
fout.open("test.txt", ios::eek:ut);
if(!fout || !fout.is_open() )
{
std::cout << "error while opening file for output.\n";
return -1;
}
for (int i=0; i<10; i++)
fout.write(reinterpret_cast<char*>(&Test1), sizeof(Test));
fout.close();

If you wrote a global operator<< to stream Test data you'ld benefit
since operators can be reused for both writing to file and writing to
std::cout.

for (int i = 0; i < 10; ++i)
{
ofs << test; // depends on global op<<
}
fstream fin;
fin.open(test.txt", ios::in);
for(int i=0; i<10; i++){
char c[sizeof(Test)];
fin.get(c, sizeof(Test));
Test t2;

Don't use char, use std::string instead.

// input file stream
std::ifstream ifs;
ifs.open("test.txt"); // its set to std::ios::in already
if(!ifs || !ifs.is_open() )
{
std::cout << "error while opening file for input.\n";
return -1;
}

// load a vector with Test data
std::vector< Test > vtest; // container
std::string buffer; // buffers each line
std::istringstream iss; // used to dissect data from buffer
while(std::getline(ifs, buffer, '\n'))
{
Test temp;
iss.str(buffer);
iss >> temp.i >> temp.j >> temp.k >> temp.l;
iss.clear();
vtest.push_back(temp); // push temp onto container
}
if(!ifs.eof()) // if std::getline did *not* fail because of eof...
{
std::cout << "error while reading file.\n";
std::cout << "end of file not found.\n";
return -1;
}
// print vector using copy algorithm
std::copy( vtest.begin(),
vtest.end(),
std::eek:stream_iterator<Test >( std::cout ));
return 0;
}

I leave the global operator<< to you as an exercise.
Have fun.
 
P

Pete Becker

fout.write(reinterpret_cast<char*>(&Test1), sizeof(Test));
fin.get(c, sizeof(Test));

Instead of get, use read. get reads text. write and read deal in binary
data. And, as Larry suggested, open the file in both cases in binary mode.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
 
D

David Harmon

On 5 Nov 2006 00:19:07 -0800 in comp.lang.c++, "Salt_Peter"
Types need a semicolon and are not placed in main()

Nothing wrong with declaring a type in main() if that is exclusively
where you are going to use it.
Either an aggregate list or Test ctor would be handy.

Test test = {99, 777, 12345, 876};

Aggregate initialization, yes. Constructor, no; it needs to be a POD
struct if he is going to binary read and write it.
If you wrote a global operator<< to stream Test data you'ld benefit
since operators can be reused for both writing to file and writing to
std::cout.

But not appropriate for the binary writing purpose.
Don't use char, use std::string instead.

His array of char is not being used as a string. But better to declare
a Test instance and read directly into that.

The main points are still: open with ios::binary flag and then use
read() and write().
 
S

Salt_Peter

David said:
On 5 Nov 2006 00:19:07 -0800 in comp.lang.c++, "Salt_Peter"


Nothing wrong with declaring a type in main() if that is exclusively
where you are going to use it.

ok, good to know
Aggregate initialization, yes. Constructor, no; it needs to be a POD
struct if he is going to binary read and write it.

yep, makes sense
But not appropriate for the binary writing purpose.


His array of char is not being used as a string.

i realize that, its not a string, its a pseudo-byte array.
But better to declare
a Test instance and read directly into that.

Thats what i want to hear, no need for the reinterpret_cast.
The main points are still: open with ios::binary flag and then use
read() and write().

Yes, it makes perfect sense and a better alternative, thank-you.
 
P

paul.anderson

THANK YOU!!! I did not realize that "read()" should be used for binary
data. Once I switched to that everything worked like a charm.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top