• Advertisement

Archived

This topic is now archived and is closed to further replies.

what object to use to read a file in it?

This topic is 5000 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi to everyone! I''d like to read a whole file into an object (the file is at most around 350KB) and then read the object instead of the file. Right now I''m reading from the file each time and it slows down my app. (I''m trying to do a replay system) I''m almost sure it''s the file access that slows it down because I''m using the same program, slightly alter where I read a certain type of event (only the mouse move) into a vector and then the replay goes fine. Currently I''m reading the file like this:
void Idle()
{
	static double dEventTime = 0;
	unsigned char ucEventType;
	short int mouseX = 0;
	short int mouseY = 0;

	GLint viewport[4];
	GLdouble mvmatrix[16], projmatrix[16];
	GLint realy; // OpenGL y coordinate position 

	GLdouble wx, wy, wz; // returned world x, y, z coords 


	if (g_bIsPlaying && ((g_cTimer->ElapsedTime()/* - g_dTimeOfLastEvent*/) >= dEventTime)) {
		//int filePos = g_TraceFile.tellg();

		g_dTimeOfLastEvent = g_cTimer->ElapsedTime();
		g_TraceFile.read((char*)&ucEventType, sizeof(unsigned char));
		g_TraceFile.read((char*)&dEventTime, sizeof(double));
		//filePos = g_TraceFile.tellg();

		switch (ucEventType) {
		case gc_ucEC_MouseMove:
			g_TraceFile.read((char*)&mouseX, sizeof(short int));
			g_TraceFile.read((char*)&mouseY, sizeof(short int));
			//filePos = g_TraceFile.tellg();

			glGetIntegerv (GL_VIEWPORT, viewport);
			glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
			glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);
			// note viewport[3] is height of window in pixels 

			realy = viewport[3] - (GLint) mouseY - 1;
			gluUnProject ((GLdouble) mouseX, (GLdouble) realy, 0.0,
			mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
			g_fFingerX = wx;
			g_fFingerY = wy;
			g_cTraceLine.push_back(wx);
			g_cTraceLine.push_back(wy);
			// mouse moved

			break;
		case gc_ucEC_MouseButton:
			g_TraceFile.read((char*)&g_bMouseButtonDown, sizeof(bool));
			// button changed

			break;
		}
	}
	if (g_bMouseButtonDown && g_cBalls[g_cBalls.size() - 1].Clicked(g_fFingerX, g_fFingerY)) {
		g_bCursorIsMoving = true;
	}
	if (!g_bMouseButtonDown) {
		g_bCursorIsMoving = false;
	}
	if (g_bCursorIsMoving) {
		g_cBalls[g_cBalls.size() - 1].MoveBall(g_fFingerX, g_fFingerY);
	}
}
What I''d like to do is the same thing only, read from memory, not from a file. Are sstreams any good? Thank you for your time.

Share this post


Link to post
Share on other sites
Advertisement
Yeah, you'll want to use streams. As a matter of fact, you're already using a stream to read from the file. What you'll do is copy the whole file to memory, and wrap that memory into a stream. Then your code won't really have to change at all!

// Copy file to string

ifstream fileStream("filename.dat");
string fileData;
fileData.assign( istreambuf_iterator<char>(fileStream),
istreambuf_iterator<char>() );
fileStream.close();
//

// Create buffer

streambuf streamBuffer;
streamBuffer.sputn(fileData.c_str(), fileData.length());
//

// Create the stream

istream dataStream(&streamBuffer);

And that's one way you could do it. Just use dataStream in place of what you use now. Although I'm sure someone more familiar with streams, buffers, and iterators will show me up with a better way of doing it. As a matter of fact, I'm sure they will

EDIT: Almost forgot, make sure the stream buffer has at least the same lifetime as the stream, otherwise you'll have problems.

[edited by - Zipster on June 10, 2004 1:43:31 PM]

Share this post


Link to post
Share on other sites
That will probably work, but if all you''re reading is raw binary data (no formatting or operator >>, etc.), then there''s a faster way to do it:
std::ifstream g_TraceFile; // File stream

std::vector<char> g_TraceFileData; // File data

int g_TraceFileDataSize; // Data size

char *g_pNextTraceFileItem; // Pointer to next item to be read from memory


...

g_TraceFile.open("foo.bar");
g_TraceFile.seekg(0, std::ios::end); // Go to end of file

g_TraceFileDataSize = g_TraceFile.tellg(); // Count how many bytes


g_TraceFileData.resize(g_TraceFileDataSize); // Allocate memory


g_TraceFile.seekg(0, std::ios::beg); // Go back to the beginning of the file

g_TraceFile.read(&g_TraceFileData[0], g_TraceFileDataSize); // Read in all the data

g_pNextTraceFileItem = &g_TraceFileData[0]; // Set pointer to first byte


...

assert(g_pNextTraceFileItem - &g_TraceFileData[0] < g_TraceFileDataSize - 9); // Make sure we have more data; you can get rid of this if you want


ucEventType = *(unsigned char *)g_pNextTraceFileItem; g_pNextTraceFileItem += sizeof(unsigned char); // Read an unsigned char

dEventTime = *(double *)g_pNextTraceFileItem; g_pNextTraceFileItem += sizeof(double); // Read a double

Share this post


Link to post
Share on other sites
Here's another way that I think is closer to what the original
poster was asking:

struct MyData {
float x, y, z;
};

MyData data;

// Open up binary data file for reading
FILE* in = fopen("data.bin", "rb");
fread(&data, sizeof(MyData), 1, in);

There's a few things you need to be carful about here though:
(1) This won't work if the structure you're reading contains
pointers.
(2) The structure can't contain a v-table. In other words,
the object should't have any virtual functions.

[edited by - d_emmanuel on June 10, 2004 5:21:57 PM]

Share this post


Link to post
Share on other sites
To add to what d_emmanuel suggested - if you take that approach, make sure that your structs are packed. If you create a struct with an unsigned char and a double, it is likely that the struct size will be 12 (not 9, as some might expect), because things ged padded to multiples of 4 bytes. To ensure that your structs are packed, do the following:

#pragma pack(push, 1)

struct MyData
{
unsigned char ucEventType;
double dEventTime;
};

#pragma pack(pop)


The compiler keeps a stack of the current packing state, so the above code makes sure that the packing state will be the same afterwards as it was before.

Share this post


Link to post
Share on other sites

  • Advertisement