File IO...

Hello,
Let me preface this question with I have been up and down google to no avail looking for the problem. I'm having a problem using iterators and STL with file IO, here is the code:

#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;

int main( void ) {

vector<short> vo(5);
for(size_t j = 0; j < 5; j++){
cout << j << "\t";
vo[j] = j;
}
cout << endl;

fstream out( "shorts.bin", ios::binary|ios::out| ios::trunc );
out.write(reinterpret_cast<char *>(&vo[0]),sizeof(short)*vo.size());
out.close();

ifstream in( "shorts.bin", ios::binary|ios::in );

std::vector<short> vi;
vi.insert( vi.begin(), istream_iterator<short>(in), istream_iterator<short>() );
in.close();

cout << "Size: " << vi.size() << "\t";
for(size_t j = 0; j < vi.size(); j++){
cout << vi[j] << "\t";
}
cout << endl;

return 0;
}

I have proven I'm at least writing out the correct number of bytes, but I'm not reading in anything - vi.size() comes up as 0. This feels like such a silly problem, and I'm hoping someone can give me a quick hand squaring it away.

Thanks for your help & time -
Anthony
Maybe you didn't look hard enough.
Ten minutes produced the following information form :
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=257

text as follows:
1
2
Writing a Stream to a Container
To read a file into a container, use the copy algorithm, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
#include <fstream>
#include <algorithm>
#include <cstdlib>
#include <iostream>
using namespace std;

int main()
{
 vector<int> vi;//vector to be filled
 ifstream vi_dump("vi.txt"); //open for read
 if (!vi_dump)
 {
  cerr<<"couldn't open file";
  exit(1);
 }
 copy(istream_iterator<int> (vi_dump),
   istream_iterator<int> (),
   back_inserter(vi));
}


1
2
3
4
5
6
7
8
9
10
11
copy() writes the file's data into vi. 

There's one quirk here that novices might find surprising. If we'd written:

copy(istream_iterator<int> (vi_dump),
   istream_iterator<int> (),
   vi);
The code wouldn't have compiled, because the third argument isn't an iterator. 
vi.begin() is much worse because vi is empty at this stage. 
If the container to which you are writing is empty, you need to use a special type of an iterator. 
back_inserter(vi) returns a special output iterator that automatically causes vi to allocate storage for incoming data as needed. 
Hello,
Actually I did find that link, and I couldn't get the code to work. I tried it again, and I modeled my example after the link:

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

using namespace std;

int main( void ) {

	vector<short> vo(5);
	for(size_t j = 0; j < 5; j++){
		cout << j << "\t";
		vo[j] = j;
	}
	cout << endl;

	fstream out("shorts.bin", ios::binary|ios::out|ios::trunc );
	out.write(reinterpret_cast<char *>(&vo[0]),sizeof(short)*vo.size());
	out.close();
	
	ifstream in("shorts.bin", ios::binary|ios::in );
	if(!in){
		cout << "couldn't open file\n";
		exit(1);
	}

	std::vector<short> vi;
	copy(istream_iterator<short>(in), istream_iterator<short>(), back_inserter(vi));
	//vi.insert( vi.begin(), istream_iterator<short>(in), istream_iterator<short>() );
    in.close();

	cout << "Size: " << vi.size() << "\t";
	for(size_t j = 0; j < vi.size(); j++){
		cout << vi[j] << "\t";
	}
	cout << endl;

	return 0;
}


It still doesn't work... I feel like I must be doing something silly, but I don't see it. Do you see the error?

Thanks -
Anthony
I'm messing about with it even as we speak.
It seems it all depends on how the file is written and read.
Like you say, I does not behave quite the way you would expect.
I'm still experimenting :-)
Yes, I understand it now.
It is all to do with the way the file is wriiten and then read.
We were dumpng the vector to file in binary format. The copy function is expecting standard stream format - that is why nothing was being read back in.

You can copy out a a file and copy in from a file - but it is stanard formatting stream stuff.

So if you use the the write data function, you will have to use the read function.

So with all that said, here is how you would 'copy' a vector to a ostream and back from a istream (in this case we are using files streams).
p.s it wouldn't matter if the files open modes include ios::binary.

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 <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <iterator>

using namespace std;

int main( void ) {

vector<short> vo(5);
for(size_t j = 0; j < 5; j++){
cout << j << "\t";
vo[j] = j+3;
}
cout << endl;

fstream out( "shorts.bin",ios::out| ios::trunc );


ostream_iterator<short> os(out," ");
copy(vo.begin(), vo.end(), os);

out.close();


ifstream in( "shorts.bin",ios::in);


vector<short> vi;
istream_iterator<short> in_start(in);
istream_iterator<short> end;

copy(in_start, end,back_inserter(vi));

in.close();

cout << "Size: " << vi.size() << "\t";
for(size_t j = 0; j < vi.size(); j++){
cout << vi[j] << "\t";
}
cout << endl;

return 0;
}
That does work. Thank you for the help, I appreciate it.

Anthony
Topic archived. No new replies allowed.