0

I'm trying to create a saving/loading system. While I've created tons of ASCII parsers, I'm not so used to binary ones. Currently, if I pass a small value, say 2, it works. So does. 11. 10 returns 13, and 412 returns -100. I'm using buffers which I can precalculate the size of before reading, but I'm getting incorrect values anyways.

This is part of a saver method:

FILE *ptr_myfile;

ptr_myfile = fopen("data.sav", "wb");
uint32_t bufferSize = 4;
char *writeBuffer = (char*)malloc(bufferSize);

int value = 412;
memcpy(&writeBuffer, &value, sizeof(value));

fwrite(&writeBuffer, sizeof(char), sizeof(writeBuffer), ptr_myfile);

fclose(ptr_myfile);

And this is part of a loader method:

FILE *ptr_myfile;

ptr_myfile = fopen("data.sav", "rb");

//Get file length
fseek(ptr_myfile, 0, SEEK_END);
unsigned long fileLen = ftell(ptr_myfile);
fseek(ptr_myfile, 0, SEEK_SET);

char *buffer = (char *)malloc(fileLen + 1);
if (!buffer) {
    fprintf(stderr, "Memory error!");
    fclose(ptr_myfile);
    return;
}

fread(buffer, fileLen, 1, ptr_myfile);

printf("%i\n", (int)buffer[0]);

fclose(ptr_myfile);

Thanks in advance!

  • 1
    This looks way more like C than C++, and would not even be good as the former. Where did you get the idea that this is how to write binary data in C++? You need to stop trying to learn C++ by trial and error, that *really* will not work. Same goes for C, that's just as bad. – Baum mit Augen Aug 23 '16 at 10:22
  • `(int)buffer[0]` only cast first element of `buffer` to `int`. Also, using `memcpy` to serialize provide a non portable solution – Garf365 Aug 23 '16 at 10:33
  • @BaummitAugen I'm not sure what you're referring to. I'm using FILE * because I once read it's faster, but even if it isn't, isn't it just as competent? All f* functions are C, I'm simply opening a file, creating a buffer, copying to it, and then moving it to the file using fwrite, and doing the same with fread? Could you be specific in what you mean? – Karim Abdel Hamid Aug 23 '16 at 10:34
  • 1
    For starters: `char *writeBuffer = (char*)malloc(bufferSize);` don't do this in C++. `fwrite(&writeBuffer, sizeof(char), sizeof(writeBuffer), ptr_myfile);` that's just wrong in both C and C++. Also, this `memcpy` business is completely unnecessary to begin with. Really, choose C or C++ and learn whatever you chose systematically from a good book. – Baum mit Augen Aug 23 '16 at 10:38
  • @Garf365 Wouldn't it still work in this case? I'm only trying to get it to work once, then I'll rework it to work depending on the loaded entity type. The plan is to have a string represent the class type, and then to create it and push all the data based on a restore method. (ie: 9 npc_human 3 bob 24 65, where 9 is the length of npc_human, npc_human is the class "name", 3 is the length of bob is the entity's name, 24 is hp, and 65 is ammo). – Karim Abdel Hamid Aug 23 '16 at 10:39
  • I agree with @BaummitAugen, if you want to use C++, use it correctly (_ie_ don't produce C like code in C++; prefer container than raw memory, smart pointer than raw pointer, use new instead of malloc, ...) and look how to serialize/deserialize and save in file in C++... or use only C but correctly (for example, never cast a malloc - http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Garf365 Aug 23 '16 at 10:45
  • @Garf365 Okay, I'll try to convert it to pure-C++ even though my code currently works by Sam's solution. But is my method of serialization appropriate considering it's binary? Or would JSON or something similar be a better alternative? The only issue I can think of with my solution is a discrepancy between versions having a different number/type of fields – Karim Abdel Hamid Aug 23 '16 at 11:33
  • You have not to use high level serialization like JSON, take a look at http://stackoverflow.com/questions/37430047/converting-bytes-array-to-integer – Garf365 Aug 23 '16 at 11:38
  • @Garf365 I'm sorry Garf, but I fail to understand how this even qualifies as deserialization. It's simply, from what I understand, bitwise casting (and isn't this super-C based? There's no std library to help with that?) I understand that it'll help me gather ints the char * array, but not much beyond that. – Karim Abdel Hamid Aug 23 '16 at 12:01
  • If you want to save your data in a binary format, to avoid trouble, you have to convert everything into a char buffer (serialization) and write it where you want. After that, you will read a char buffer that you have to reconstruct original data (deserialization). For binary format, you have to use bitwise operator – Garf365 Aug 23 '16 at 12:04

1 Answers1

2
char *buffer = (char *)malloc(fileLen + 1);

Buffer is an array of chars.

printf("%i\n", (int)buffer[0]);

This prints the value of buffer[0], which is a single character, after casting it to an int.

Your code that wrote the binary file did not manage to stuff an entire int into the first character in the file, obviously. It memcpyed the int into a character buffer.

To read this back, the process is reversed, exactly: memcpy() the character buffer into an int variable.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Thanks! This worked. memcpy(&value, buffer, sizeof(int)); for anyone looking into this. I'm going to try rewrite the code since apparently, it's terrible anyways XD But I still really appreciate it, Sam! – Karim Abdel Hamid Aug 23 '16 at 11:20