Reputation: 15658
I would like to write a binary image of a structure array to a binary file. I have tried this so far:
#include <stdio.h>
#include <string.h>
#define NUM 256
const char *fname="binary.bin";
typedef struct foo_s {
int intA;
int intB;
char string[20];
}foo_t;
void main (void)
{
foo_t bar[NUM];
bar[0].intA = 10;
bar[0].intB = 999;
strcpy(bar[0].string,"Hello World!");
Save(bar);
printf("%s written succesfully!\n",fname);
}
int Save(foo_t* pData)
{
FILE *pFile;
int ptr = 0;
int itr = 0;
pFile = fopen(fname, "w");
if (pFile == NULL) {
printf("couldn't open %s\n", fname);
return;
}
for (itr = 0; itr<NUM; itr++) {
for (ptr=0; ptr<sizeof(foo_t); ptr++)
{
fputc((unsigned char)*((&pData[itr])+ptr), pFile);
}
fclose(pFile);
}
}
but the compiler is saying aggregate value used where an integer was expected fputc((unsigned char)*((&pData[itr])+ptr), pFile);
and I don't quite understand why, what am I doing wrong?
Thanks!
Upvotes: 1
Views: 196
Reputation: 154169
Ensure file is opened in binary mode.
// pFile = fopen(fname, "w");
pFile = fopen(fname, "wb");
Cast to char *
pointer before indexing. Original code indexes by the sizeof(pData[itr])
. [Edit] and then dereferenced the type - then tries to cast to unsigned char
@R Sahu
//fputc((unsigned char)*((&pData[itr])+ptr), pFile);
unsigned char *p = (unsigned char *) (&pData[itr]);
fputc(p[ptr], pFile);
As @R Sahu pointed out: fclose()
should be moved outside the loops.
Minor:
Recommend passing NUM
is as argument to save()
.
foo_t bar[NUM];
is not fully initialized.
The non-loop solution is
if (fwrite(pData, sizeof(*pData), NUM, pFile) == NUM) Success();
Suggest making const
: `int Save(const foo_t* pData)
Better to use size_t
for ptr
& itr
Upvotes: 1
Reputation: 206717
Problem 1
Use the right mode for opening the file.
pFile = fopen(fname, "wb");
Problem 2
The call to fclose
is in the wrong place.
for (itr = 0; itr<NUM; itr++) {
for (ptr=0; ptr<sizeof(foo_t); ptr++)
{
fputc((unsigned char)*((&pData[itr])+ptr), pFile);
}
fclose(pFile);
}
You are closing the file after writing out the data of the first foo_t
. Subsequent calls will result in undefined behavior since you will be calling fputc
using a FILE*
that has been closed.
The call to fclose
must be moved out of the loops.
for (itr = 0; itr<NUM; itr++) {
for (ptr=0; ptr<sizeof(foo_t); ptr++)
{
fputc((unsigned char)*((&pData[itr])+ptr), pFile);
}
}
fclose(pFile);
Problem 3
The way you are trying to access a byte in the loops is incorrect. Here are the loops:
for (itr = 0; itr<NUM; itr++) {
for (ptr=0; ptr<sizeof(foo_t); ptr++)
{
fputc((unsigned char)*((&pData[itr])+ptr), pFile);
}
}
Here's the line you are trying to get a byte.
fputc((unsigned char)*((&pData[itr])+ptr), pFile);
^ ^
This is of type `foo_t*`
fputc((unsigned char)*((&pData[itr])+ptr), pFile);
^ ^
This pointer arithmetic is done on `foo_t*`.
It is not pointer arithmetic done on `char*`.
You are going to run into out of bound memory access
very quickly.
fputc((unsigned char)*((&pData[itr])+ptr), pFile);
^ ^
This is dereferencing a `foo_t*`, which
means it is of type `foo_t`.
You are getting the compiler error since you are trying to cast a foo_t
to an unsigned char
.
To save a foo_t
, you can take two approaches. You can use fwrite
to save an entire foo_t
in one call.
for (itr = 0; itr<NUM; itr++) {
fwrite(&(pData[itr]), sizeof(foo_t), 1, pFile);
}
If you must write each byte using fputc
, which I don't think is needed, you will have to change your code a little bit.
The following should work:
for (itr = 0; itr<NUM; itr++) {
cp = (char*)&pData[itr]; // Declare char* cp in the function.
for (ptr=0; ptr<sizeof(foo_t); ptr++)
{
fputc(cp[ptr], pFile);
}
}
Upvotes: 2
Reputation: 893
To write into the binary file you need to open the file in w+b mode. and then use fwrite to write into the file. It should work.
pFile = fopen(fname, "w+b");
Instead of fputc use fwrite.
fwrite ((foo_t *)&pData[itr], sizeof(foo_t), 1, pFile);
Upvotes: 1
Reputation: 6333
i think all you need to do is just write it.
foo_t fooarry[SOME_SIZE];
fd = open(fname, O_WRONLY);
write(fd, fooarry, SOME_SIZE * sizeof(foo_t));
UPDATE: if you want to use file stream, go like this:
fwrite(fooarry, siezeof(foo_t), SOME_SIZE, pFile);
Upvotes: 0