Allocating file memory in a multiple inheritence construct

Sorry for posting again so quickly.

I am having some trouble with my constructor, basically I need to use the values I receive in my constructor and instantiate 2 base classes and 1 derived class.
The class TFL is made by deriving it from the fstream class and a class called TextField.

Once the variable have been instantiated the TFL must use the functions seekg() and tellg() to dynamically determine how large the file is before loading the contents of the file into memory using only one call to the read() function, and this is where I'm having trouble.

So far this is what I got:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

TextFieldLoader::TextFieldLoader(/*const */char *fn, int row, int col, int width, int height)
			: fstream(fn), TextField(fn, row, col, width, height){
	
	int length;
	//determining the size of the file
	//move to end of file
	seekg(ios::beg, ios::end);
	//get length
	length = tellg();
	//move to start of file
	//seekg(0, ios::beg);

	//read into memory
	read(fn, length);
}

The base constructors have been initialized without a problem I'm not sure what to do after that, basically with the seekg() tellg() and read(). All I am getting is the name of the file to appear not the data it contains.
Last edited on
Sorry
Why?

I think this is what you meant to do:
1
2
3
4
5
std::ifstream file(fn,std::ios::ate);
unsigned l=file.tellg();
file.seekg(0,std::ios_base::beg);
char *buffer=new char[l];
file.read(buffer,l);
Last edited on
I don't think I explained myself properly.

This is what I am supposed to do.

The TextFieldLoader class will have only one constructor and MUST accept
the following parameters only:
1. filename (const char *) that will be used to read (and store) the entire
contents of the file into memory.
2. row (int), and
3. column (int) representing where on the screen the TextFieldLoader is
located.
4. width (int), and
5. height (int) representing the TextFieldLoader's dimensions.

Once instantiated, the TextFieldLoader must use the functions seekg( ) and
tellg( ) to dynamically determine how large the file is before loading
the contents of the file into memory using only one call to the read( )
function.

The base class TextFields constructor receives the filename as a variable TextField(fn, row, col, width, height) fn is the name of the file and also where variable should be stored.

This is what I got so far:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TextFieldLoader::TextFieldLoader(/*const */char *fn, int row, int col, int width, int height)
			: fstream(fn), TextField(fn, row, col, width, height){
	
	int length;
	//determining the size of the file
	//move to end of file
	seekg(ios::beg, ios::end);
	//get length
	length = tellg();
	//move to start of file
	seekg(/*0,*/ ios::beg);
	
	//read into memory
	read(*page_, length);
}
Last edited on
If TextFieldLoader just initialises itself with the contents of a file (and possibly updates the file later on), there's no reason for it to contain a member fstream class.

Simply use the std::ifstream within the constructor and let it go once you've read your data.

File handles are a finite resource. One day someone may want to keep a collection of TextFieldLoaders, then you'd have real trouble.

Oh, I almost forgot. As for your memory, you seem to need a contiguous block of memory to mirror your file. Why not use an std::vector. You can resize it once you work out how large it needs to be.
Last edited on
kbw: std::vector is not read()-friendly.
What do you mean? It provides a contiguous block of memory of known length.
But read() needs an actual buffer. You can't pass it an std::vector.
istream& read ( char* s, streamsize n );
Nonsense.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <vector>
#include <iostream>
#include <fstream>
#include <sys/stat.h>

int main()
{
        // this file
        const char filename[] = "a.cpp";

        // make vector large enough to hold file
        struct stat stbuf;
        stat(filename, &stbuf);
        std::vector<char> buffer(stbuf.st_size);

        // open file and read it
        std::ifstream is("a.cpp");
        is.read(&buffer[0], stbuf.st_size);

        // write file's content to stdout
        std::cout << &buffer[0] << std::endl;

        return 0;
}
Hm... I'm not sure that's safe.
It is (safe and valid) in all existing implementations of the STL.

Part of the reason is explicit design -- a vector is a wrapper around an array of objects. Hence, if you need (for legacy reasons or even something convenient like this) you can directly access the underlying array.

The trick is just to remember that the array's address may change -- so you must always use the vector's methods to get the current address instead of storing it anywhere -- or be careful to keep the vector from reallocating.

Also, you must make sure there is actually some capacity to the vector... otherwise you'll get NULL.


After all that, there is a better way:
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
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
#include <sys/stat.h>
using namespace std;

int main()
  {
  // This is the file we are interested in
  string filename( "a.cpp" );

  // Make the data buffer (our vector) large enough to hold it
  struct stat stbuf;
  stat( filename.c_str(), &stbuf );
  vector <char> buffer( stbuf.st_size );

  // Read the entire file into our buffer
  ifstream f( filename.c_str() );
  f >> noskipws;
  copy(
    istream_iterator <char> (f),
    istream_iterator <char> (),
    buffer.begin()
    );
  f.close();

  // Write the entire file to stdout
  copy(
    buffer.begin(),
    buffer.end(),
    ostream_iterator <char> (cout)
    );

  return 0;
  }

Hope this helps.
Last edited on
Topic archived. No new replies allowed.