1

I've been searching all over the web, implementing the information as shown, but for reasons I don't understand, I can't get this very simple code to work. It's supposed to be a simple sanity check. I'm using FILE* for speed (speed being the priority here). First, the variables...

#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

int main()
{

//Declaration
int g = 1, dim_hi = 5, pop = 6;//variables I'll use to write to binary file
char OA = 'D';//variable I'll use to write to binary file

const short d_size = sizeof(double);
const short c_size = sizeof(char);
const short i_size = sizeof(int);
FILE * outFile;

int read_g = 0, read_dim = 0, read_pop = 0;//variables I'll use to READ from file
char read_oa ='a';//variable I'll use to READ from file

Next I write to the file. As far as I can tell (based on the size of the output file) this section of code is working properly. My intent is to write three integers and a char to the file, one after another...

//Binary File Output
outFile = fopen ("myfile.bin", "ab");
fwrite (&dim_hi , i_size, i_size, outFile);
fwrite (&pop , i_size, i_size, outFile);
fwrite (&g , i_size, i_size, outFile);
fwrite (&OA , c_size, c_size, outFile);
fclose (outFile);

According to the internet, I should have a file that, in binary, contains the values: 561D. However, according to the following code...

//Binary File Input
outFile = fopen ("myfile.bin", "rb");
fread ((void*)&read_dim , i_size, 1, outFile);
fread ((void*)&read_pop , i_size, 1, outFile);
fread ((void*)&read_g , i_size, 1, outFile);
fread (&read_oa , c_size, 1, outFile);
fclose (outFile);

return 0;
}

Note I've also tried (char*)&read_dim, and simply &read_dim. What I get is:

read_dim = 5
read_pop = -858993460
read_g = -858993460
read_oa = 9 "

I don't get it. It's a list of writes and a list of reads. Same system, etc. Why don't the writes correspond to the reads? I've read something about padding, but none of the examples use seekg (or an equivalent command for FILE*) objects to move around in the file.

Does anything know what's wrong with this code?

Once I sort out the issues with this simple test, I want to do something similar with rows of a matrix (this matrix can eventually contain tens of thousands of elements)...

vector<vector<double> > depop(pop, vector<double> (dim_hi,0));
short v_size = dim_hi*d_size;
for(int i = 0; i < pop; i++)
{
    fwrite (&depop[i] , d_size, v_size, outFile);
}
// followed by the read command...

Thank you all in advance!

Links I've read:

Community
  • 1
  • 1
Eric Inclan
  • 327
  • 1
  • 5
  • 14
  • Did you *look* at the *parameters* for [`fwrite`](http://en.cppreference.com/w/c/io/fwrite)? It takes an address, the size of **a** (singular) item, the **number of *items***, and the file pointer. Consequently, `fwrite (&dim_hi , i_size, i_size, outFile);` is wrong. Look at your third param. This is repeated throughout your code. – WhozCraig Jun 13 '14 at 00:30
  • Good catch. My follow-up question is to everyone (since all the responses were the same). Since I was using i_size, i_size and i_size = 4, then why didn't I get: read_dim = 5, read_pop = 5, read_g = 5, read_oa = *garbage* ?? – Eric Inclan Jun 13 '14 at 01:19

3 Answers3

5

According to cplusplus.com, fwrite's third argument is the count of the number of elements to write, so you should have:

fwrite (&dim_hi , i_size, 1, outFile);
fwrite (&pop , i_size, 1, outFile);
fwrite (&g , i_size, 1, outFile);
fwrite (&OA , c_size, 1, outFile);

to match with your validating calls to fread, since i_size is most likely greater than 1 (typical size of int being 4).

SleuthEye
  • 14,379
  • 2
  • 32
  • 61
  • 1
    It would be even better to use `fwrite(&x, sizeof x, 1, outFile);` . Then there is no possible doubt about writing the correct number of bytes. – M.M Jun 13 '14 at 00:31
  • I would also add that using `"ab"` mode to open the file means that you never overwrite what's been written on the first run of the program. – ach Jun 13 '14 at 01:00
2

Your problem is that the third argument you're passing to fwrite is not correct. See:

fwrite (&dim_hi , i_size, i_size /* <-- here */, outFile);

The man-page on fwrite says:

// The function fwrite() writes nmemb elements of data, each size bytes long...
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

This means you need to tell the size of each element, and how many elements you wish to write. From your code, it's clear that you want to write only 1 element. So you should do this:

fwrite (&dim_hi , i_size, 1 /* <-- here */, outFile);
jweyrich
  • 31,198
  • 5
  • 66
  • 97
1

There are two excellent answers here, and I have one comment. If you are going to do lots of binary input/output get a good hex-editor for your platform. In this case, you could have opened the file you created and checked to see if the data was correct. With your data (and assuming a 32-bit little-endian architecture you would expect to see):

0x05 0x00 0x00 0x00 0x06 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x44

as the only contents of your file. Your mileage may vary but I find it helpful (and a better sanity check) to look at the contents of the file.

thurizas
  • 2,473
  • 1
  • 14
  • 15