readFile and LPVOID

Started by
10 comments, last by CyberSlag5k 19 years, 2 months ago
I believe alot of my binary I/O headaches can be solved using microsoft's readFile function. I have a few questions, though, if anyone has any experience using it. First of all, what, exactly, is an LPVOID type? I can't really find anything about it on google or MSDN. I know it's a like a pointer to the buffer the memory will be stored in when readFile is called, but how am I to access the data? Can I just go to whatever byte I want and just read in and cast the data however I chose? So like if I know there are 4 bytes of float at bytes 80, 84, and 88 can I just do:

float one, two, three;
one = float(lpBuffer[80]);
two = float(lpBuffer[84]);
three = float(lpBuffer[88]);

And will the compiler know how to take the 4 binary bytes and convert them to a float? Or do I access the data some other way?
Without order nothing can exist - without chaos nothing can evolve.
Advertisement
Ok, I've done a little more research. This function is actually pretty cool. I have another question, though. The prototype for the readFile function is as follows:

BOOL ReadFile(    HANDLE  hFile,                 // handle of file to read     LPVOID  lpBuffer,              // address of buffer that receives data      DWORD  nNumberOfBytesToRead,   // number of bytes to read     LPDWORD  lpNumberOfBytesRead,  // address of number of bytes read     LPOVERLAPPED  lpOverlapped     // address of structure for data    );


That has almost everything I need. I specify the handle to the file to be read, the buffer to store what is read into, the number of bytes to read...what I'm missing, though, is how to specify where reading should begin. I'd like to use the function in the middle of a loop. The data I'm reading has an 80 byte header and then any number of blocks of data following. So I'd like to read in that 80 byte buffer, enter the loop, read in the block of data, and then loop if I'm not at the end of the file. But it appears as though there's no pointer to track where I've read from so far. So it looks as though every time the ReadFile function is called, it starts from the beginning. Say it isn't so...
Without order nothing can exist - without chaos nothing can evolve.
It starts from where it last finished. Use SetFilePointer(Ex) to seek forwards, backwards, or to a specific byte.

LPVOID = void *. It has no idea of what data it holds, and thus, cannot be indexed. You can do this though.

*((float*)&((char*)myvoidptr)[mybyteoffset]);
(ie: convert to char *, offset it in bytes, convert to float *, then dereference it to get the actual float).
Wow, that's quite a bit of casting. This article I found here on file i/o declares an array of DWORDs and just passes that in as the lpBuffer parameter. Can I not just do something similar with floats?

Here's the article:
http://www.gamedev.net/reference/articles/article707.asp
Without order nothing can exist - without chaos nothing can evolve.
You can pass whatever you like where you see a LPVOID. E.g.
float fBuffer[10];DWORD dwRead=0;ReadFile(hFile,fBuffer,sizeof(float)*10,&dwRead,NULL);

Thanks for everyone's help so far. I've written the preliminary version of my function just to see if everything I've learned so far is working. It appeared to have worked the very first time it was run. The screen opened and it was outputting what appeared to be proper values, but it closed immediately (on a side note does anyone know how I can disable that in MSVS.net) so I really didn't get a chance to check anything. I ran it again to see if it was really working and this time nothing read successfully. The first two ReadFile calls returned false, and it hangs at that point.

I am lead to believe I am clobbering something on accident. I can't really check to see if the file has been corrupted (as it is binary), but it's still the same size as before. Can someone see if I'm doing something illegal:

void loadListBin(){	Vector normVector;	Vector tempVector;	float float1, float2, float3;	char header[80];	float *buffer;	HANDLE hFile;	DWORD numRead = 0;	bool readSuccess;	int *numFacets = new int;	hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);		readSuccess = ReadFile(hFile, header, sizeof(char) * 80, &numRead, NULL);	cout << "readSuccess = " << readSuccess << endl;	cout << "numRead = " << numRead << endl << endl;	readSuccess = ReadFile(hFile, numFacets, sizeof(int), &numRead, NULL);	cout << "readSuccess = " << readSuccess << endl;	cout << "header = " << header << endl;        cout << "number of facets = " << *numFacets << endl << endl;	buffer = new float[*numFacets];	readSuccess = ReadFile(hFile, buffer, sizeof(float) * *numFacets, &numRead, NULL); 	cout << "readSuccess = " << readSuccess << endl;	cout << "numRead = " << numRead << endl << endl;	cout << "Normal 1 = " << buffer[0] << endl;	cout << "Normal 1 = " << buffer[4] << endl;	cout << "Normal 1 = " << buffer[8] << endl;		cout << "Vertex 1 = " << buffer[12] << endl;	cout << "Vertex 1 = " << buffer[14] << endl;	cout << "Vertex 1 = " << buffer[16] << endl;	delete [] buffer;	delete numFacets;	CloseHandle(hFile);}


I delete my buffers and close the file...what have I missed?

EDIT: Perhaps I have to inform the file it will be reading binary? Or will it take care of that on its own?

[Edited by - CyberSlag5k on February 11, 2005 10:17:23 AM]
Without order nothing can exist - without chaos nothing can evolve.
You never check that CreateFile() returns a valid handle. It'll return INVALID_HANDLE_VALUE if it can't open the file.
Aside from that, the code seems to work for me. Are you sure the file contains the correct data?

Also, you don't need this: int *numFacets = new int;. You can just do int numFacets;, and pass the address of the variable to ReadFile.

I usually prevent the console application from closing immediately by putting a breakpoint on the last line of main(). Or you could put an assert(false);, and include assert.h, or you could include process.h and do system("pause");.
If you want a proper way to do it, that'll work erliably in release mode as well as debug mode, you need to read data from cin and wait for the user to hit enter.
Quote:Original post by Evil Steve
You never check that CreateFile() returns a valid handle. It'll return INVALID_HANDLE_VALUE if it can't open the file.
Aside from that, the code seems to work for me. Are you sure the file contains the correct data?


Haha, silly mistake on my part. I had a space in between the file name and the extension so it wasn't getting the file correctly. I added that check in there which helped me identify the problem. Thanks.

Quote:
Also, you don't need this: int *numFacets = new int;. You can just do int numFacets;, and pass the address of the variable to ReadFile.


Good call.

Quote:
I usually prevent the console application from closing immediately by putting a breakpoint on the last line of main(). Or you could put an assert(false);, and include assert.h, or you could include process.h and do system("pause");.
If you want a proper way to do it, that'll work erliably in release mode as well as debug mode, you need to read data from cin and wait for the user to hit enter.


Yeah that's what I have been doing.


Great, so everything appears to be working properly (for now). Thanks a ton guys :).
Without order nothing can exist - without chaos nothing can evolve.
Correction, all is not well. Should I have casted something differently? Some of my values are quite screwy:

<-5.59009e-033, -5.01574e+018, -1.#QNAN>
<4.03392e+018, 6.07491e-039, 41.6217>
<6.96617e-017, 3.15394e-008, 1.62267e+032>
<-5.01574e+018, -1.#QNAN, 4.03392e+018>
<6.07491e-039, 41.6217, 6.96617e-017>
<3.15394e-008, 1.62267e+032, 1.15072e-040>
<-1.#QNAN, 4.03392e+018, 6.07491e-039>
<41.6217, 6.96617e-017, 3.15394e-008>
<1.62267e+032, 1.15072e-040, 1.03773e-026>
<4.03392e+018, 6.07491e-039, 41.6217>
<6.96617e-017, 3.15394e-008, 1.62267e+032>

I've never even seen #QNAN before, and the e###'s make me a little concerned. Plus, none of these values should be negative (although sometimes certain exporters break that convention. Does the e stuff suggest I should be using doubles? I think I might anyway, just to be safe. So yeah, these values are garbage, I think, but the rest of my stuff reads in ok.

Here's the new routine for processing the buffer data:

	readSuccess = ReadFile(hFile, buffer, sizeof(float) * numFacets, &numRead, NULL);	if(readSuccess == false)		exit(456);    for(int i = 0; i < numFacets; i++)	{		normVector.setVector(buffer[0 + (i*4)], buffer[4 + (i*4)], buffer[8 + (i*4)]);		normalList.InsertItem(normVector);		tempVector.setVector(buffer[12 + (i*4)], buffer[16 + (i*4)], buffer[20 + (i*4)]);		vertexList.InsertItem(tempVector);		tempVector.setVector(buffer[24 + (i*4)], buffer[28 + (i*4)], buffer[32 + (i*4)]);		vertexList.InsertItem(tempVector);		tempVector.setVector(buffer[36 + (i*4)], buffer[40 + (i*4)], buffer[44 + (i*4)]);		vertexList.InsertItem(tempVector);	}


EDIT: It would be nice to be able to check my data to see what the values should actually be. I've tried a few hex viewers I found on download.com but they just came up gibberish. Anyone know a good (free) application for viewing binary files? The data is stored as floats, if that makes any difference.

[Edited by - CyberSlag5k on February 11, 2005 1:26:48 PM]
Without order nothing can exist - without chaos nothing can evolve.
Another question, is there a maximum size for these things? I have some pretty gigantic files. Since I'm dynamically allocating the buffer/array of floats, I should be able to load in files until I run out of available program memory, right?
Without order nothing can exist - without chaos nothing can evolve.

This topic is closed to new replies.

Advertisement