Sign in to follow this  
Eddy999999

C++ Inputting Integer from Pythons Pack()

Recommended Posts

I have a tool which I made in Python to compress a bunch of files in a directory into a single resource file. The very first 4 bytes of the file is an integer telling how many files are contained in the resource file. In my Python tool, I wrote the integers to the file using Pythons struct.pack() method, but I'm having trouble reading the number from my game, which is written in C++. I though I could just use ifstream.read() to read the first 4 bytes from the file, and convert it to an integer, but when I tested it with a sample resource file (named python.res), the ouput was 3624856, when it should have been 12. Here's my function:
/* Retrieves a compressed file from a resource file
	resname - The name of the resource file to access
	filename - The name of the file within the resource file
	result - The string to place the file into
	Return - Negative values indicate errors
*/
int getResource(string resname, string filename, string *result) {
	char *temp=new char();
	ifstream resfile;
	resfile.open(resname.c_str(),ios::in); //Open the file
	//Read the first four bytes of the file, and output the resulting integer
	resfile.read(temp,4);
	cout << temp << "\n" << (unsigned int)temp;
	return 0;
}

Also, I'm almost positive the output to the file is correct, because I have been able to write a program (also in python) to unpack the files, which works perfectly. Does anyone know why I am getting a different number in my C++ program? Thanks in advance, -Eddy

Share this post


Link to post
Share on other sites
There a few problems with your code. First off, you allocate memory for exactly one byte in your new statement, but read four. Secondly, when you open the file for reading you don't use the binary flag. Third, when you output the value you output the value of temp, the pointer to the memory, which isn't related at all to the value you read. You probably want something more like:

int getResource(string resname, string filename, string *result) {
int value;
ifstream resfile(resname.c_str(), ios::binary);
resfile.read(reinterpret_cast<char *>(&value), 4);
cout << value << "\n";
return 0;
}

Share this post


Link to post
Share on other sites
I actually originally had allocated for four bytes, and used the binary flag, but I changed it when I was trying other things, and I forgot to change it back when I posted the code.

Anyways, the problem was that I was outputting the value of temp, rather than what was stored at the address, as you stated. I'm just so used to not having to use the indirection operator when outputting char pointers that I didn't put it there when I changed it to an int value.

Thanks =D

Share this post


Link to post
Share on other sites
Now I have a new problem: I can't get any values above 255. For example, if I store a value of 300, then when I try to get it in my C++ program, I get a value of 44 (300-256). I'm assuming this has something to do with the fact that there are only 256 ASCII values, but I'm not sure how to fix it...

EDIT: If I read the bytes one by one, for the value 300, for example, I get 44 1 0 0. So I can obviously multiply the second byte by 256^1, the third by 256^2, and the fourth by 256^3, and add them all up. Is this the easiest and/or most efficient way to do it?

[Edited by - Eddy999999 on March 7, 2008 9:55:58 PM]

Share this post


Link to post
Share on other sites
Well, what's your code look like now? Are you using the function I posted, or modified the one you posted?

Share this post


Link to post
Share on other sites
Nevermind, I got it. Here's my code though, in case you know of an easier way to do it:


int getResource(string resname, string filename, string *result) {
unsigned char *temp=new unsigned char();
char *numfiles=new char[4];
unsigned long curpos; //Running total for the current file position
vector<unsigned long> filepos; //A vector containing the positions of each file within the resource file
ifstream resfile;
resfile.open(resname.c_str(),ios::in | ios::binary); //Open the file
//Get the number of files contained in the resource file
resfile.read(numfiles,4);
cout << "Number of files: " << (int)*numfiles << "\n";
//Get the positions of all of the files within the resource file
//And store them in the filepos vector
for (int i=0; i<(int)*numfiles; i++) {
cout << "Getting position of file number " << i << "\n";
curpos=0;
for (int j=0; j<4; j++) {
resfile.read((char*)temp,1);
curpos+=(unsigned long)*temp * (unsigned long)pow(256.0,j);
}
cout << " position: " << curpos << "\n";
}
return 0;
}

Share this post


Link to post
Share on other sites
Quote:
cout << "Number of files: " << (int)*numfiles << "\n";


This is only dereferencing one byte. Since numfiles is an array of 4 chars, you're going to have to recast this into a pointer to unsigned long then dereference that to get what you want.
*reinterpret_cast<unsigned long *>(numfiles)


But there's no need for that, SiCrane's solution is what you want to use.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this